pub struct Platform { /* private fields */ }Expand description
A running platform: the sequencer plus the shared view it maintains.
Implementations§
Source§impl Platform
impl Platform
Sourcepub fn start(
registry: Registry,
log: Box<dyn OpLog>,
node_key: ActorKey,
) -> Result<Self, String>
pub fn start( registry: Registry, log: Box<dyn OpLog>, node_key: ActorKey, ) -> Result<Self, String>
Replays log into a view and starts the admission sequencer over
it with registry as the trusted key set plus the daemon’s own
node_key (registered automatically, for git-derived ops).
§Errors
Returns a description of any replay failure (a log written through this platform always replays cleanly).
Sourcepub fn start_with_review_retention(
registry: Registry,
log: Box<dyn OpLog>,
node_key: ActorKey,
retention: ReviewRetention,
) -> Result<Self, String>
pub fn start_with_review_retention( registry: Registry, log: Box<dyn OpLog>, node_key: ActorKey, retention: ReviewRetention, ) -> Result<Self, String>
Platform::start with explicit live-review retention.
Retention is a startup choice because recovering FIFO request order belongs in the same replay pass that builds the view. The ordinary constructor allocates no tracker and performs no retention checks.
§Errors
Same as Platform::start.
Sourcepub fn start_reloading(
registry: Registry,
log: Box<dyn OpLog>,
node_key: ActorKey,
keys_file: Option<PathBuf>,
) -> Result<Self, String>
pub fn start_reloading( registry: Registry, log: Box<dyn OpLog>, node_key: ActorKey, keys_file: Option<PathBuf>, ) -> Result<Self, String>
Platform::start with a trusted-keys file that is hot-reloaded
(on mtime change) before signature verification: registering a key
is appending a line, no restart, and removing one refuses its next
submission. The file’s contents replace the whole registry.
§Errors
Same as Platform::start.
Sourcepub fn start_reloading_with_review_retention(
registry: Registry,
log: Box<dyn OpLog>,
node_key: ActorKey,
keys_file: Option<PathBuf>,
retention: ReviewRetention,
) -> Result<Self, String>
pub fn start_reloading_with_review_retention( registry: Registry, log: Box<dyn OpLog>, node_key: ActorKey, keys_file: Option<PathBuf>, retention: ReviewRetention, ) -> Result<Self, String>
Sourcepub fn with_newcomer_audit(
self,
audit_path: PathBuf,
adjudications_path: PathBuf,
incumbent_actor_keys: Vec<String>,
) -> Result<Self, String>
pub fn with_newcomer_audit( self, audit_path: PathBuf, adjudications_path: PathBuf, incumbent_actor_keys: Vec<String>, ) -> Result<Self, String>
Enables sparse, durable D24 T4 newcomer measurement.
incumbent_actor_keys is the trusted-key snapshot at activation;
those actors are excluded because the audit cannot reconstruct their
first attempt or time-to-first-acceptance. The audit records only a
later actor’s first verified signed-API attempt, its first eventual
acceptance, and an optional appeal. Operator adjudications are JSONL
rows in the separate file and are re-read for every report.
Both files are created mode 0600. Neither changes the signed op log or any hash input.
§Errors
Unusable paths or an invalid existing audit file.
Sourcepub fn with_review_adjudications(self, path: PathBuf) -> Result<Self, String>
pub fn with_review_adjudications(self, path: PathBuf) -> Result<Self, String>
Enables the D24 T2 operator classification file: versioned 0600 JSONL
rows of {"format_version":1,"review_id":…,"classification":…} where
classification is valid, invalid, slop or unclear.
Separate from the signed op log on purpose, exactly like the T4 adjudications: a judgement about a contribution is the operator’s opinion, not a sequenced claim any actor can make. Keying it by review id rather than by verdict is what lets a classification outlive archiving, which discards the verdict bulk.
Enabling it does not make T2 evaluable. The cohort still has no exit rule, the observation window and tripwire subject are unset, and census adjudication cannot survive the flood it would need to detect.
§Errors
The file or its directory cannot be created.
Sourcepub fn with_required_assignment(self) -> Self
pub fn with_required_assignment(self) -> Self
Refuses any RequestReview that names its own reviewers, so the
node’s draw is the only path to a reviewer list (D24 layer 5,
“the requester does not choose who reviews them” — enforced
rather than merely offered).
Requires a reviewer pool: without one no review can ever be assigned, so every request would stall unassigned.
Scope: node-wide, the blunt instrument. For “only reviews landing
somewhere that matters”, see Platform::with_protected_refs,
which conditions on RequestReview’s target_ref.
Sourcepub fn with_protected_refs(self, path: PathBuf) -> Self
pub fn with_protected_refs(self, path: PathBuf) -> Self
Points the platform at an operator-curated list of protected refs
(one <repo>:<refname> pattern per line, # comments allowed, a
single trailing * acting as a prefix glob). A RequestReview
whose target_ref matches must go through the node’s draw; one
naming an unprotected ref, or naming no ref at all, may still pick
its own reviewers.
This is the per-review half of D24 layer 5 — “privilege-bearing”
finally has a definition the code can read, rather than the
node-wide approximation of Platform::with_required_assignment.
Requires a reviewer pool, for the same reason.
On its own this only binds reviews: a requester who omits
target_ref still escapes it. Platform::with_required_review
is the other half, and closes that.
Sourcepub fn with_acl_file(self, path: PathBuf) -> Self
pub fn with_acl_file(self, path: PathBuf) -> Self
Points the admission policy at the operator’s ACL file, so a landing on a protected ref can ask who owns the repository (D42).
Without this the ownership rule is simply absent and every
protected ref keeps the approval-weight gate, which is the
behaviour of every node built before D42. Ownership is opt-in per
repository even once the file is attached: a repository nobody
holds own over is unaffected.
The path, not a parsed table, because the file is hot-reloadable
and admission must see an ownership change without a restart —
the same reason Platform::with_protected_refs takes a path.
Sourcepub fn attach_accounts(&self, store: Arc<Accounts>)
pub fn attach_accounts(&self, store: Arc<Accounts>)
Gives the admission policy the credential store, so a submission signed by an enrolled passkey can be verified (D39).
A setter rather than a constructor argument because accounts and the platform are enabled independently, in either order, by separate flags. Until this is called a passkey submission is refused for want of a store, which is the same answer a node without self-service gives permanently.
Sourcepub fn with_required_review(self) -> Self
pub fn with_required_review(self) -> Self
A protected ref only moves to a commit that an approved review
with weight from two distinct operators already named as its
destination, and can never be deleted.
This is the landing half of the gate: with it, omitting
target_ref stops being an escape and becomes a refusal, because
the push itself is what gets checked.
Requires Platform::with_protected_refs — with no list nothing
is protected and the flag would do nothing.
No exemption for the node’s own key. Every git push reaches the
sequencer as a node-signed SetRef, so exempting the node would
exempt every push. The consequence is deliberate and operational:
switching this on means this daemon’s own repository can only be
advanced through a review, choirctl sync included.
Creating a protected ref is allowed (prev == None): there is no
history to hijack yet, and since deletion is refused, “delete then
re-create” is not a way back in.
Not covered, and not silently implied: force-pushes and
non-fast-forward updates are only constrained by the CAS prev
git itself supplies. A sufficiently weighted approval of commit X
authorizes landing X, whether or not X is a descendant of the
current tip.
Sourcepub fn with_required_scope(self) -> Self
pub fn with_required_scope(self) -> Self
Admits only ops whose author bound them to this log and a head still in the window — the replay defence, turned on.
Off by default because it is a wire-compatibility break, not because unscoped is safe: an unscoped signature is admissible on any node that trusts the key, and admissible again on the node it came from as soon as CAS state returns to what it expected. Every client in this repository always sends a scope, so turning this on costs them nothing; a client that predates scopes stops working, which is the whole reason for the flag.
Sourcepub fn scope_now(&self) -> (ContentHash, Option<ContentHash>)
pub fn scope_now(&self) -> (ContentHash, Option<ContentHash>)
The log identity a client signs a scope against: this node’s actor id and the head it should name.
Sourcepub fn proposal_round(&self, repo: &str, branch: &str) -> Option<ProposalRound>
pub fn proposal_round(&self, repo: &str, branch: &str) -> Option<ProposalRound>
The round of proposals aimed at branch of repo (D68).
None when the branch does not exist. A round with no proposals
is Some with an empty list: “nobody has proposed anything” and
“there is nothing to propose to” are different answers, and only
the second is a misconfiguration.
Sourcepub fn ref_landing(&self, refname: String, base: &str) -> RefLanding
pub fn ref_landing(&self, refname: String, base: &str) -> RefLanding
A landing that moves refname from base, signed by this node.
The scope is read per landing rather than captured here, because
a round appends as it goes; see crate::queue::ScopeSource.
Sourcepub fn check_reporter(
&self,
name: String,
target_ref: Option<String>,
) -> CheckReporter
pub fn check_reporter( &self, name: String, target_ref: Option<String>, ) -> CheckReporter
A check reporter that this node signs and scopes (D49, D68).
The reason set_check_reporter was off by default and composed
into nothing: the identity a check is reported under belongs to
whoever runs the queue, and a bridge has no node-side identity to
use. A node does – its own key – and its landings are in a log
that is kept rather than thrown away, so a report against them is
answerable later.
Sourcepub fn run_proposal_queue(
&self,
repo: &str,
branch: &str,
workdir: &Path,
ci: &mut dyn CiExecutor,
template: JobTemplate,
) -> Option<QueueReport>
pub fn run_proposal_queue( &self, repo: &str, branch: &str, workdir: &Path, ci: &mut dyn CiExecutor, template: JobTemplate, ) -> Option<QueueReport>
Runs one speculative round over this node’s own log (D5, D68).
workdir must be a worktree of the repository this node
serves, made with git worktree add --detach against the bare
repo, and owned outright by the queue: every speculative merge
detaches it and forces it to a candidate state, so a tree
anybody else is working in is the wrong argument.
A worktree and not an independent clone, and this is not a
preference. A landing names the merge commit the speculator
built. An independent clone writes that commit into its own
object store, where the served repository cannot see it, so the
log would name a commit git does not have — which
Platform::reconcile_git_refs correctly reads as the view
being wrong and compensates back to git’s value, silently
undoing every landing in the round. A worktree shares the object
store, so the commit is already there when the op is submitted.
None when the branch does not exist. Otherwise the report says
what landed, in order, and every landing in it is an op in this
node’s log rather than a number the round kept to itself.
Sourcepub fn drain_queue(
&self,
queue: &mut MergeQueue,
ci: &mut dyn CiExecutor,
) -> QueueReport
pub fn drain_queue( &self, queue: &mut MergeQueue, ci: &mut dyn CiExecutor, ) -> QueueReport
Drains a caller-built queue through this node’s sequencer.
The escape hatch under Platform::run_proposal_queue, for a
caller whose round is not simply “every proposal on this
branch”. The sequencer is the point: a landing recorded through
anything else is not in the log this node serves.
Sourcepub fn with_log_path(self, path: PathBuf) -> Self
pub fn with_log_path(self, path: PathBuf) -> Self
Points the platform at the JSON-lines file its op log persists to,
so /api/log?from= can serve entries that have already been
evicted from the in-memory window. Without it, a reader that has
fallen further behind than the window is told so and cannot
resync.
The file is append-only, so reading a prefix while the writer thread appends is safe: already-written lines never change.
Sourcepub fn with_batch_limit(self, max_ops: usize) -> Self
pub fn with_batch_limit(self, max_ops: usize) -> Self
Sets the absolute operation-count ceiling for one batch request.
Sourcepub fn set_key_names(&self, signers: &[TrustedKey])
pub fn set_key_names(&self, signers: &[TrustedKey])
Replaces the actor-id → bound-name map from a freshly parsed trusted-keys file.
Called from the daemon’s accept loop when the file’s mtime moves, so binding a name to an already-trusted key takes effect on the next request rather than waiting for some later signature failure. That matters because a binding is a tightening: a gate that applies at an unpredictable future moment is not a gate.
Sourcepub fn with_log_window_cap(self, cap: usize) -> Self
pub fn with_log_window_cap(self, cap: usize) -> Self
Shrinks the in-memory /api/log window. Exists so tests can
exercise eviction and the resync path without writing 100k ops.
Sourcepub fn with_reviewer_pool(self, path: PathBuf) -> Self
pub fn with_reviewer_pool(self, path: PathBuf) -> Self
Points the platform at an operator-curated pool of eligible
reviewer names (one per line, # comments allowed). With a pool
set, a RequestReview carrying an empty reviewer list is
answered by a node-signed OpKind::AssignReviewers drawn from
the pool, excluding the requester — D24 layer 5, so a requester
cannot pick a friendly reviewer.
Sourcepub fn with_reviewer_conflict_graph(
self,
path: PathBuf,
max_distance: usize,
) -> Self
pub fn with_reviewer_conflict_graph( self, path: PathBuf, max_distance: usize, ) -> Self
Excludes reviewer operators whose shortest path from the requester
in path is at most max_distance. Each non-comment line is one
undirected <operator> <operator> edge. Operator names, not full
operator/agent channels, belong in the graph.
The graph is operator-supplied runtime policy rather than op-log state: changing it affects future draws without changing persisted operations or replay. It is read for every draw and fails closed; an unreadable or malformed graph leaves the review unassigned. Distance zero retains the existing same-operator exclusion.
Source§impl Platform
impl Platform
Sourcepub fn git_update(
&self,
repo: &str,
refname: &str,
old_hex: &str,
new_hex: &str,
user: &str,
cert: Option<(&str, &str)>,
) -> Result<(), String>
pub fn git_update( &self, repo: &str, refname: &str, old_hex: &str, new_hex: &str, user: &str, cert: Option<(&str, &str)>, ) -> Result<(), String>
Routes one git ref update (from a repo’s update hook) through
the sequencer: CAS against the view, node-signed, totally ordered
with API ops. Refs are namespaced <repo>:<refname>; git oids
enter the envelope with their own codec (ContentHash::from_git_oid).
A push to refs/for/<branch>/<topic> additionally opens a review
targeting that branch, which is the whole magic-refspec path: one
git push, no client but git, and reviewers drawn by the node.
§Errors
The policy’s rejection reason (stale CAS = concurrent update git
itself would also have refused), or the reason a refs/for/ push
could not be read as a proposal.
Sourcepub fn git_abort(
&self,
repo: &str,
refname: &str,
old_hex: &str,
new_hex: &str,
user: &str,
cert: Option<(&str, &str)>,
) -> Result<(), String>
pub fn git_abort( &self, repo: &str, refname: &str, old_hex: &str, new_hex: &str, user: &str, cert: Option<(&str, &str)>, ) -> Result<(), String>
Retracts a ref op this push already had accepted, because the push as a whole is being refused and git will apply none of it.
pre-receive submits one op per ref but git applies no ref until
the hook exits zero, so a push whose third ref is refused has
already put two ops in the durable log. Without this the view keeps
refs git never created — and they cannot be pushed afterwards
either, because the pusher’s old is git’s (absent) value while
the view holds the stranded one, so every retry loses the CAS. The
ref becomes permanently unpushable.
The log is append-only, so the repair is a compensating op, not an
erasure: the abort is part of the history rather than hidden from
it. old/new are the same values the accepted op carried, so the
inverse restores exactly what git still has.
§Errors
The policy’s rejection reason — most likely a lost CAS, meaning something else moved the ref between the accept and this retraction and the stranded value is no longer what would be undone.
Sourcepub fn reconcile_git_refs(&self, root: &Path) -> RefReconciliation
pub fn reconcile_git_refs(&self, root: &Path) -> RefReconciliation
Brings every bare repo under root back into agreement with the
view, which is the source of truth. Run at startup, before the
node serves anything, so nothing races the repair.
The hook’s retraction path handles a push that is refused while
the daemon is alive. This handles the rest, and it does so without
needing to know which of them happened: power loss between the
hook’s 200 and git writing the ref, a per-ref failure after
pre-receive passed (receive.deny*, an update hook, a write
error), or a retraction that could not be delivered. All of them
leave the same state, and it is the state this reads.
Two repairs, chosen by whether git can honour the view:
- the commit exists in the repo, so git is simply behind: the ref is written. Git is the follower (D21 single-canonical), so moving it is the defined direction.
- the commit is absent — a refused push has its objects discarded from the quarantine — so the view names something git can never have: a compensating op puts the view back to git’s value.
A ref git holds and the view does not is reported, never
adopted. Appending an op for it would launder an out-of-band
update-ref into the signed log as though it had been submitted.
Sourcepub fn survey_git_refs(&self, root: &Path) -> Vec<RefFinding>
pub fn survey_git_refs(&self, root: &Path) -> Vec<RefFinding>
Every way the repos under root and the view currently disagree,
with nothing written and no op appended.
This is the half of Platform::reconcile_git_refs that can be
run against a live node. The repair deliberately cannot: it writes
refs, so it belongs before the first request, where nothing races
it. Reading is safe at any time, and without it a divergence that
appears while the daemon is up is invisible until the next
restart — which is the difference between a monitor and an
autopsy.
Served by GET /api/ref-agreement, which is deliberately its own
endpoint rather than a field on /api/view: this shells out to
git once per repo, and /api/view is on the hot path.
Scope, stated because RefState::GitOnly reads like a stronger
claim than it is: only repos the log already names are compared.
A repo with refs and no log entry at all is not surveyed, so this
finds an out-of-band ref beside logged ones, not an entire
smuggled repo.
Sourcepub fn set_workspace_head(
&self,
workspace: &str,
head_hex: &str,
attribution: &str,
) -> Result<(), String>
pub fn set_workspace_head( &self, workspace: &str, head_hex: &str, attribution: &str, ) -> Result<(), String>
Points workspace at git oid head_hex with a node-signed op,
using the view’s current head as the CAS prev (a lost race is
a sequencer rejection, not a clobber). attribution is the
submission channel (e.g. git/<user>), as for git-derived ops.
§Errors
Bad oid, or the policy’s rejection reason.
Sourcepub fn create_change(
&self,
request: AuthorizedChangeCreate<'_>,
attribution: &str,
) -> Result<Accepted, String>
pub fn create_change( &self, request: AuthorizedChangeCreate<'_>, attribution: &str, ) -> Result<Accepted, String>
Atomically creates a stable change and registers its workspace at an exact Git revision with a node-signed operation.
Sourcepub fn decode_create_change_request(
&self,
request: &Value,
expected_id: &str,
expected_owner: &str,
expected_workspace: &str,
expected_revision: &ContentHash,
expected_idempotency_key: &str,
) -> Result<(Witness, Vec<String>), String>
pub fn decode_create_change_request( &self, request: &Value, expected_id: &str, expected_owner: &str, expected_workspace: &str, expected_revision: &ContentHash, expected_idempotency_key: &str, ) -> Result<(Witness, Vec<String>), String>
Decodes the exact owner-signed create binding before any physical workspace is copied. Sequencer admission verifies the embedded signature before recording the node-authored change operation.
Sourcepub fn submit_archive_change(
&self,
request: &Value,
expected_id: &str,
expected_workspace: &str,
expected_revision: &ContentHash,
attribution: &str,
) -> Result<Accepted, String>
pub fn submit_archive_change( &self, request: &Value, expected_id: &str, expected_workspace: &str, expected_revision: &ContentHash, attribution: &str, ) -> Result<Accepted, String>
Submits a node-authored OpKind::ArchiveChange carrying the
owner’s signed authorization, after verifying that the signed
payload names exactly the resource the endpoint already moved.
Sourcepub fn validate_archive_change_request(
&self,
request: &Value,
expected_id: &str,
expected_workspace: &str,
expected_revision: &ContentHash,
) -> Result<(), String>
pub fn validate_archive_change_request( &self, request: &Value, expected_id: &str, expected_workspace: &str, expected_revision: &ContentHash, ) -> Result<(), String>
Checks the archive request’s signed payload shape before the filesystem is renamed. Signature and current-state admission still happen on the sequencer after the rename, with rollback on refusal.
Sourcepub fn archive_change_receipt(
&self,
request: &Value,
expected_id: &str,
expected_workspace: &str,
expected_revision: &ContentHash,
attribution: &str,
) -> Option<(u64, ContentHash)>
pub fn archive_change_receipt( &self, request: &Value, expected_id: &str, expected_workspace: &str, expected_revision: &ContentHash, attribution: &str, ) -> Option<(u64, ContentHash)>
Original operation identity for an identical completed archive request still present in the durable log window.
Sourcepub fn change_state(&self, id: &str) -> Option<ChangeState>
pub fn change_state(&self, id: &str) -> Option<ChangeState>
Current materialized state for one stable change.
Sourcepub fn change_for_idempotency(
&self,
owner: &str,
key: &str,
) -> Option<(String, ChangeState)>
pub fn change_for_idempotency( &self, owner: &str, key: &str, ) -> Option<(String, ChangeState)>
Finds the change created by one owner-scoped idempotency key.
Sourcepub fn archived_change_ids_for_workspace(&self, workspace: &str) -> Vec<String>
pub fn archived_change_ids_for_workspace(&self, workspace: &str) -> Vec<String>
Inactive change generations that previously used workspace.
This supports migration of the original unversioned archive path
when a later generation reuses a deterministic workspace name.
Sourcepub fn workspace_head(&self, workspace: &str) -> Option<ContentHash>
pub fn workspace_head(&self, workspace: &str) -> Option<ContentHash>
Current exact head of an active workspace.
Sourcepub fn workspaces_held_by(&self, channel: &str) -> usize
pub fn workspaces_held_by(&self, channel: &str) -> usize
How many workspaces channel currently holds (D37).
Read from the projection replayed out of the op log, so a node that has just restarted answers the same number it answered before — the property a per-user ceiling is worthless without.
Sourcepub fn tallied_workspaces(&self) -> Vec<String>
pub fn tallied_workspaces(&self) -> Vec<String>
Every workspace the D37 tally is tracking, sorted.
Exposed for the test that pins the tally against
View::workspaces: the two are folded from the same operations
and a divergence between them is the tripwire on the D37 register
row.
Sourcepub fn assign_reviewers(
&self,
id: &str,
requester: &str,
) -> Result<Vec<String>, String>
pub fn assign_reviewers( &self, id: &str, requester: &str, ) -> Result<Vec<String>, String>
Draws reviewers for unassigned review id and records them with
a node-signed op.
Candidates are the pool minus everyone sharing the requester’s
operator and, when configured, every operator within the chosen
conflict-graph distance. The draw takes at most one reviewer per
operator so REQUIRED_APPROVAL_WEIGHT reviewers means that many
independent ones under the configured policy.
Excluding only the requester’s own name was the original rule and it does not survive the multi-operator case, which is the normal one: an operator running three agents in the pool satisfies two-person integrity by themselves, and can manufacture more agreement by registering more agents. That is the Sybil move D24 says must be blocked at the operator level, so the exclusion has to be at that level too.
A pool that cannot supply REQUIRED_APPROVAL_WEIGHT distinct operators
draws fewer rather than doubling up — a visibly under-assigned
review beats one that looks independent and is not.
§Errors
No pool configured, an unreadable pool or conflict graph, malformed graph data, no candidate outside the conflict distance, or the sequencer’s rejection reason (e.g. the review was assigned by a concurrent request).
Sourcepub fn durability_failed(&self) -> bool
pub fn durability_failed(&self) -> bool
Whether the sequencer has failed a durability barrier and stopped accepting.
The daemon’s accept loop polls this so a node that can no longer persist exits rather than staying up refusing everything. Process supervision only restarts a process that exits, so without this a transient fsync error is permanent downtime that looks like uptime.
Sourcepub fn with_journal(self, path: &Path) -> Result<Self>
pub fn with_journal(self, path: &Path) -> Result<Self>
Records every admission decision to path as JSONL.
Derived data (see journal): the file is appended to from its
own thread, never read back, and its loss or truncation changes
no decision this node makes. Safe to rotate by moving it aside;
the daemon keeps writing to the open handle until restarted.
§Errors
If path cannot be opened for append.
Sourcepub fn with_lag_log(self, path: PathBuf) -> Self
pub fn with_lag_log(self, path: PathBuf) -> Self
Appends gate breaches to path, one JSON object per line.
Separate from the op log on purpose: a breach is an observation about this node’s storage and load, not a fact about the ordered history, and it must not change a hash anyone else replays.
Sourcepub fn with_hooks(self, config: PathBuf, log: PathBuf) -> Result<Self, String>
pub fn with_hooks(self, config: PathBuf, log: PathBuf) -> Result<Self, String>
Enables outbound ref-landed webhooks (D32) from the subscription
file config, recording every delivery attempt in log.
Starts one delivery thread. The sequencer’s writer thread never
waits on it: it offers events to a bounded queue and drops
(counted, and written to log) when that queue is full, because
a receiver this node does not control must not be able to delay
op admission. See crate::hooks.
§Errors
Returns a message when the subscription file cannot be read or does not parse, or when the delivery thread cannot be started.
Sourcepub fn hook_drops(&self) -> u64
pub fn hook_drops(&self) -> u64
Events the webhook queue dropped because it was full. Zero when
no --hooks-file is configured.
Sourcepub fn lag(&self) -> Arc<LagMeter>
pub fn lag(&self) -> Arc<LagMeter>
The live latency record, for a caller that wants to tighten the gate or read it without going through the API.
Sourcepub fn drain_lag_log(&self)
pub fn drain_lag_log(&self)
Writes any breaches recorded since the last drain to the lag log.
Called by the daemon’s accept loop, which is the same place it polls for a failed durability barrier: both are things the writer thread can only report, never act on. No traffic means no drain, which is harmless because no traffic also means no breaches.
Sourcepub fn view_seq(&self) -> u64
pub fn view_seq(&self) -> u64
The sequence the next admitted op will occupy, which is the cheapest complete description of “what state is this node in”.
Exposed for the browser surface’s cache: it asks this before
deciding whether to rebuild a page, so an unchanged node costs
one u64 read rather than a full view serialization.
Sourcepub fn roster(&self) -> (u64, BTreeMap<String, String>)
pub fn roster(&self) -> (u64, BTreeMap<String, String>)
The store’s generation and the handle-to-name map to render channels through (D46).
Both together because a caller that resolves names has to cache on the generation the map was read at: revoking an account deletes a name and appends no op, so the view sequence does not move and a page keyed on it alone would keep showing the deleted name.
(0, empty) on a node with no accounts store attached, which
resolves nothing and renders every channel as itself — the same
answer a store gives for an account issued before D46 or issued
with an explicit user.
Sourcepub fn review_repo(&self, id: &str) -> Option<String>
pub fn review_repo(&self, id: &str) -> Option<String>
Repository the review id proposes to land on, in the canonical
D29 spelling, or None when the review is unknown or unbound.
Exposed for per-repository authorization: it is what lets posting a verdict require write on the repository under review, instead of the node-wide grant every review op would otherwise need.
Sourcepub fn review_json(&self, id: &str) -> Option<Value>
pub fn review_json(&self, id: &str) -> Option<Value>
One review as the API renders it, or None when no such review
exists.
Exposed for the D34 review page, which needs one review rather
than the whole view. Same review_json the API uses, so the page
and the API cannot describe a review differently.
Sourcepub fn reviews_for_repo(&self, repo: &str) -> Vec<(String, Value)>
pub fn reviews_for_repo(&self, repo: &str) -> Vec<(String, Value)>
Every review whose target ref names repo, newest id last.
A review with no target ref belongs to no repository and is omitted: it cannot be shown under one without asserting a relationship the requester never signed.
Sourcepub fn reviews_awaiting(&self, channel: &str) -> Vec<(String, String, Value)>
pub fn reviews_awaiting(&self, channel: &str) -> Vec<(String, String, Value)>
Every live review that channel was drawn for and has not
answered, paired with the repository its target ref names.
The reviewer’s own queue, which the view has always held and no page has ever shown. Three filters and no others:
- drawn:
channelis on the review’s reviewer list. Being able to read a repository is not being asked about it. - unanswered: no verdict of theirs stands. A review they have already answered is not owed, whatever anybody else has said.
- live: not archived. An archived review has dropped its verdicts, so an answer to it would land nowhere.
A review with no target ref is omitted for the same reason
Self::reviews_for_repo omits one: it belongs to no repository,
and this page’s rows are grouped by one. It cannot become
invisible that way — nothing can be drawn on a ref that is not
named.
This does no authorization. The caller filters by what the reader may read, because the ACL lives there and a second copy of that decision here is a second copy that can disagree.