pub struct Hosts { /* private fields */ }Implementations§
Source§impl Hosts
impl Hosts
pub fn hat(&self, hat_id: &str) -> Result<Option<HatRecord>>
Sourcepub fn default_hat_for_new_hosts(&self) -> Result<String>
pub fn default_hat_for_new_hosts(&self) -> Result<String>
The hat newly paired hosts get as their default.
Sourcepub fn create_hat(
&self,
name: &str,
colour: Option<&str>,
now: i64,
) -> Result<HatChange>
pub fn create_hat( &self, name: &str, colour: Option<&str>, now: i64, ) -> Result<HatChange>
A new hat, colour defaulting to DEFAULT_COLOUR.
Sourcepub fn update_hat(
&self,
hat_id: &str,
name: Option<&str>,
colour: Option<&str>,
default_for_new_hosts: Option<bool>,
) -> Result<HatChange>
pub fn update_hat( &self, hat_id: &str, name: Option<&str>, colour: Option<&str>, default_for_new_hosts: Option<bool>, ) -> Result<HatChange>
Rename a hat, change its colour, or make it the one new hosts get.
A hat stops being that default only by another taking its place, so
default_for_new_hosts is Some(true) or absent.
Sourcepub fn path_rules(&self, host_id: &str) -> Result<Option<Vec<PathRule>>>
pub fn path_rules(&self, host_id: &str) -> Result<Option<Vec<PathRule>>>
A host’s path rules, longest prefix first; None for an unknown
host.
Sourcepub fn replace_path_rules(
&self,
host_id: &str,
rules: &[NewRule],
) -> Result<RulesChange>
pub fn replace_path_rules( &self, host_id: &str, rules: &[NewRule], ) -> Result<RulesChange>
Replace a host’s path rules with rules, in one transaction (kernel
spec §8: the full set). Each prefix must already be canonical and
each hat the owner’s; no two rules share a prefix. / is refused:
it is what the host’s default hat is for (the review’s O2). So is a
prefix with an invisible format character, which could display as
another path (O6). A rule whose prefix was there before keeps its id.
Sourcepub fn resolve_hat(
&self,
host_id: &str,
path: &str,
) -> Result<Option<Resolution>>
pub fn resolve_hat( &self, host_id: &str, path: &str, ) -> Result<Option<Resolution>>
The hat path resolves to on host_id (kernel spec §5.2), from
one read of the host’s default hat and its rules; None for an
unknown host. path must be canonical: anything else is an error,
never a guess.
Sourcepub fn session_hat(
&self,
host_id: &str,
path: &str,
) -> Result<Option<SessionHat>>
pub fn session_hat( &self, host_id: &str, path: &str, ) -> Result<Option<SessionHat>>
The hat a session whose canonical cwd is path gets on host_id
(umbrella §8.2), unless a rule that misses only by case makes it
ambiguous (near_miss); None for an unknown host. path must be
canonical. The host’s default hat and its rules are read in one
transaction, so a rules change or a default change committed in
between cannot mix the old one with the new (plan 5a’s final review).
Sourcepub fn rules_name_other_hats(&self, host_id: &str) -> Result<bool>
pub fn rules_name_other_hats(&self, host_id: &str) -> Result<bool>
Whether one of the host’s rules names a hat other than its default:
rules only. This is half of whether the host is mixed (umbrella
§8.5), which the gateway’s fallback needs; the other half is a live
session of another hat than the default (a default changed since it
started), which only the sessions module knows (the review’s A1).
false for an unknown host.
Sourcepub fn update_host(
&self,
host_id: &str,
name: Option<&str>,
default_hat_id: Option<&str>,
) -> Result<HostChange>
pub fn update_host( &self, host_id: &str, name: Option<&str>, default_hat_id: Option<&str>, ) -> Result<HostChange>
Rename a host, or change its default hat (kernel spec §4.3), in one transaction. The hat must be the owner’s.
Sourcepub fn is_default_hat(&self, hat_id: &str) -> Result<bool>
pub fn is_default_hat(&self, hat_id: &str) -> Result<bool>
Whether hat_id is the hat new hosts get or a host’s default hat, a
revoked host’s included (plan 9c decision 10a): what a purge refuses.
Sourcepub fn is_frozen(&self, hat_id: &str) -> Result<bool>
pub fn is_frozen(&self, hat_id: &str) -> Result<bool>
Whether a purge of hat_id began (plan 9c decision 10c): from then on
nothing starts, resumes or moves in or out of it, and it is no hat for
a rule or a host’s default. Stays true once the purge is done (A7).
Sourcepub fn begin_purge(&self, hat_id: &str, now: i64) -> Result<PurgeStart>
pub fn begin_purge(&self, hat_id: &str, now: i64) -> Result<PurgeStart>
Freeze hat_id for its purge (kernel spec §5.5; plan 9c decision
10c), in one transaction that re-checks it is no default (A2):
record it in purged_hats, unless a purge before did, and delete
every rule that names it, on every host. Again on a frozen hat it
freezes again, and takes any rule that names it, so a purge that
stopped resumes from here.
Sourcepub fn finish_purge(&self, hat_id: &str) -> Result<bool>
pub fn finish_purge(&self, hat_id: &str) -> Result<bool>
The last step of hat_id’s purge (plan 9c decision 10e): delete the
hat’s row, only while it is frozen; its project recents go with it
(ON DELETE CASCADE). Its purged_hats row stays (A7). false if
there was no frozen hat to delete. Whatever still references the hat
(a rule, a host’s default, a module’s row) fails it, by its foreign
key: the hooks ran first.
Sourcepub fn purged_hats(&self) -> Result<Vec<String>>
pub fn purged_hats(&self) -> Result<Vec<String>>
Every hat the owner purged or is purging, the oldest purge first:
what forget_hat tells a host after its handshake (plan 9c decision
12, A7).
Source§impl Hosts
impl Hosts
Sourcepub fn open(path: &Path) -> Result<Self>
pub fn open(path: &Path) -> Result<Self>
Open the kernel’s tables in hennery.db (shared with the sessions
store; each migrates only its own tables).
pub fn open_in_memory() -> Result<Self>
Sourcepub fn mint_pairing_code(&self, now: i64) -> Result<PairingCode>
pub fn mint_pairing_code(&self, now: i64) -> Result<PairingCode>
Mint a single-use pairing code valid for PAIRING_CODE_TTL_SECS.
Only its hash is stored. Spent and expired codes are deleted first,
even when the mint is then refused (TooManyPairingCodes) because
MAX_LIVE_PAIRING_CODES are live, so the table stays bounded.
Sourcepub fn mint_local_pairing_code(&self, now: i64) -> Result<PairingCode>
pub fn mint_local_pairing_code(&self, now: i64) -> Result<PairingCode>
mint_pairing_code for hennery up’s own host, once at start: not
capped, so live codes minted by the operator can never stop the
all-in-one from pairing its host (a host that cannot pair ends
up). Spent and expired codes are still deleted.
Sourcepub fn enroll(
&self,
code: &str,
enrollment: &Enrollment,
now: i64,
) -> Result<EnrollOutcome>
pub fn enroll( &self, code: &str, enrollment: &Enrollment, now: i64, ) -> Result<EnrollOutcome>
Pair a host with a code (kernel spec §4.1): check the code, create the host with a fresh id, and use the code up, in one transaction. A wrong code changes nothing, so other outstanding codes stay valid.
The spend at the end repeats the same guard as the read at the start
(used_at IS NULL AND expires_at > now), so a second writer that
raced past the read still cannot double-spend the code: whichever
commits first wins, and the loser’s UPDATE matches zero rows and is
rolled back along with the host it tentatively inserted. Today the
per-Hosts mutex already serializes every call through one
connection, so this only matters across two Hosts instances (or
connections) open on the same file — which is already possible (the
sessions store opens its own) — and matters more once §1’s single
writer thread is not the only thing standing between two writers.
Sourcepub fn register(
&self,
host_id: &str,
enrollment: &Enrollment,
now: i64,
) -> Result<Registered>
pub fn register( &self, host_id: &str, enrollment: &Enrollment, now: i64, ) -> Result<Registered>
Store a host under a known id, without a code: what enroll does once
the code checks out. Also how tests pair a host under a fixed id.
Sourcepub fn check_hello(
&self,
host_id: &str,
nonce: &[u8],
protocol_version: &str,
proof: &str,
) -> Result<HelloCheck>
pub fn check_hello( &self, host_id: &str, nonce: &[u8], protocol_version: &str, proof: &str, ) -> Result<HelloCheck>
Check a hello (ACP core §3.5). The proof is verified before the
revocation is looked at, so revoked is only ever told to the
holder of the key.
Sourcepub fn record_hello(
&self,
host_id: &str,
host_version: &str,
capabilities: &Capabilities,
now: i64,
) -> Result<()>
pub fn record_hello( &self, host_id: &str, host_version: &str, capabilities: &Capabilities, now: i64, ) -> Result<()>
Update what an accepted hello reports (kernel spec §4.3).
host_version is checked against the same shape enrollment requires
(kernel spec §4.1) before it is stored. The host is authenticated at
this point, but its self-reported version string is still its own
words, not ours: a host misbehaving or compromised after pairing
should not be able to overwrite a good version with an oversized one
or one hiding characters, the same way a name could (decision 5). A
hello failing only this check is not otherwise refused — the
signature is genuine, capabilities and last_seen_at still move —
the least surprising reading of a hello that is real but reports a
version nobody should have to display.
Sourcepub fn record_mcp_isolation(
&self,
host_id: &str,
isolation: &AgentIsolation,
) -> Result<()>
pub fn record_mcp_isolation( &self, host_id: &str, isolation: &AgentIsolation, ) -> Result<()>
Store the per-agent MCP isolation of an accepted hello (plan 8e
decision E7), for the host list while the host is away. The host’s
own words, bounded as the other reported fields are: at most
MAX_AGENTS agents, each id displayable and at most 64 bytes;
others are left out.
Sourcepub fn record_workspace_roots(
&self,
host_id: &str,
reported: &[String],
) -> Result<()>
pub fn record_workspace_roots( &self, host_id: &str, reported: &[String], ) -> Result<()>
Store the workspace roots a reconciled connection of host_id
reported (decision 7): the first MAX_ROOTS that
is_displayable_path accepts. Only a reconciled connection’s count:
hennery host join’s probe sends a hello that knows nothing of
host run’s flags.
pub fn is_revoked(&self, host_id: &str) -> Result<bool>
Sourcepub fn revoke(&self, host_id: &str, now: i64) -> Result<Revoke>
pub fn revoke(&self, host_id: &str, now: i64) -> Result<Revoke>
Mark a host revoked (kernel spec §4.3). Its future hellos get
revoked; closing its connection and parking its sessions is the
caller’s part.
The read above try_revoke is only ever a hint, not a guarantee:
unlike enroll’s check-then-spend, this is two separate statements
on an autocommit connection, not one transaction, so nothing but
try_revoke’s own guard stops a second writer that already read
“not revoked” from overwriting a revoke that has since landed. If it
matches nothing for that reason, that is exactly AlreadyRevoked — a
repeated revoke is harmless either way.
pub fn host(&self, host_id: &str) -> Result<Option<HostRecord>>
Sourcepub fn list(&self) -> Result<Vec<HostRecord>>
pub fn list(&self) -> Result<Vec<HostRecord>>
Every paired host, revoked ones included, oldest first.
Source§impl Hosts
impl Hosts
Sourcepub fn hat_logo(&self, hat_id: &str) -> Result<Option<StoredLogo>>
pub fn hat_logo(&self, hat_id: &str) -> Result<Option<StoredLogo>>
hat_id’s logo, if the owner has that hat and it has one.
Sourcepub fn set_hat_logo(&self, hat_id: &str, logo: &Logo) -> Result<HatChange>
pub fn set_hat_logo(&self, hat_id: &str, logo: &Logo) -> Result<HatChange>
Give hat_id logo, replacing any it had: Done with the hat as it
is now; NotFound; or Purging for a hat frozen for its purge,
which keeps the logo it had. The freeze is checked in the statement
that would set it (plan 9c decision 10c).
Sourcepub fn clear_hat_logo(&self, hat_id: &str) -> Result<HatChange>
pub fn clear_hat_logo(&self, hat_id: &str) -> Result<HatChange>
Take hat_id’s logo away, if it has one: Done with the hat as it
is now, or NotFound. A frozen hat’s logo goes too: that is the
purge’s own direction (the review’s A6).
Source§impl Hosts
impl Hosts
Sourcepub fn subscribe(
&self,
new: &NewSubscription<'_>,
auth_session: &str,
now: i64,
) -> Result<Subscribed>
pub fn subscribe( &self, new: &NewSubscription<'_>, auth_session: &str, now: i64, ) -> Result<Subscribed>
Store the subscription new, made by the signed-in session
auth_session at now. An endpoint the owner has already is
replaced (Subscribed::Replaced), not counted twice, and keeps its
label unless new names one. The session must still be live when
the row is written (Subscribed::SignedOut; Task 1’s review): ending
it removes its subscriptions, so one stored after would outlive it.
Sourcepub fn rotate(
&self,
old_endpoint: &str,
new: &NewSubscription<'_>,
now: i64,
) -> Result<Subscribed>
pub fn rotate( &self, old_endpoint: &str, new: &NewSubscription<'_>, now: i64, ) -> Result<Subscribed>
Replace the subscription of old_endpoint with new (a push service
rotating a subscription, which the browser reports to its service
worker; the review’s A1). It keeps its id, created_at and the
session that made it, and its label unless new names one. Only an
endpoint the owner has is rotated (Subscribed::NotFound): the API
never shows endpoints, so knowing one is holding that browser.
Sourcepub fn subscriptions(&self) -> Result<Vec<Subscription>>
pub fn subscriptions(&self) -> Result<Vec<Subscription>>
Every subscription of the owner’s, oldest first.
Sourcepub fn unsubscribe(&self, id: &str) -> Result<bool>
pub fn unsubscribe(&self, id: &str) -> Result<bool>
Remove the subscription id. Whether there was one.
Sourcepub fn unsubscribe_endpoint(&self, endpoint: &str) -> Result<bool>
pub fn unsubscribe_endpoint(&self, endpoint: &str) -> Result<bool>
Remove the subscription of endpoint: a browser unsubscribing
itself, which knows its endpoint and not its id. Whether there was
one.
Sourcepub fn record_push_success(
&self,
id: &str,
endpoint: &str,
now: i64,
) -> Result<()>
pub fn record_push_success( &self, id: &str, endpoint: &str, now: i64, ) -> Result<()>
Record that a push to endpoint reached its push service at now,
clearing the subscription id’s last error (plan 10b-ii).
Sourcepub fn record_push_error(
&self,
id: &str,
endpoint: &str,
error: &str,
) -> Result<()>
pub fn record_push_error( &self, id: &str, endpoint: &str, error: &str, ) -> Result<()>
Record why a push to the subscription id at endpoint failed: a
short reason of delivery’s own, never the endpoint or the service’s
answer (plan 10a’s review, O2).
Sourcepub fn remove_gone_subscription(&self, id: &str, endpoint: &str) -> Result<bool>
pub fn remove_gone_subscription(&self, id: &str, endpoint: &str) -> Result<bool>
Remove the subscription id its push service says is gone, if it
still has the endpoint the push went to (plan 10b-ii).
Sourcepub fn prune_expired_subscriptions(&self, now: i64) -> Result<usize>
pub fn prune_expired_subscriptions(&self, now: i64) -> Result<usize>
Remove the subscriptions whose expirationTime has passed at now
(plan 10b-ii): how many.
Sourcepub fn push_policies(&self) -> Result<Vec<(String, PushPolicy)>>
pub fn push_policies(&self) -> Result<Vec<(String, PushPolicy)>>
Every hat’s push policy, the hats oldest first: the default for a hat that never had one set.
Sourcepub fn push_policy(&self, hat_id: &str) -> Result<PushPolicy>
pub fn push_policy(&self, hat_id: &str) -> Result<PushPolicy>
The push policy of hat_id: the default for a hat with none set,
and for a hat that does not exist (a session from before hats has
none).
Sourcepub fn set_push_policy(&self, hat_id: &str, policy: PushPolicy) -> Result<bool>
pub fn set_push_policy(&self, hat_id: &str, policy: PushPolicy) -> Result<bool>
Set the push policy of hat_id. false, and nothing stored, when
the owner has no such hat.
Source§impl Hosts
impl Hosts
Sourcepub fn remember(
&self,
host_id: &str,
hat_id: &str,
path: &str,
now: i64,
) -> Result<bool>
pub fn remember( &self, host_id: &str, hat_id: &str, path: &str, now: i64, ) -> Result<bool>
Remember that a session of hat_id started or resumed in path on
host_id at now, keeping the newest KEPT of that host and hat.
false, and nothing remembered, for a path that is not canonical or
cannot be shown: until the host resolves a session’s cwd (hats 5b),
it is what its client sent.
Sourcepub fn recents(
&self,
host_id: &str,
hat_id: &str,
limit: usize,
) -> Result<Vec<Recent>>
pub fn recents( &self, host_id: &str, hat_id: &str, limit: usize, ) -> Result<Vec<Recent>>
The newest limit recents of host_id whose path resolves to
hat_id now (kernel spec §5.3; the review’s A1): resolved against
the host’s current rules and default hat, not the hat stored when
each was remembered, which a rule or a default changed since leaves
stale. Empty for an unknown host.