pub struct DeployStore { /* private fields */ }Expand description
Implementations§
Source§impl DeployStore
impl DeployStore
Sourcepub fn new(storage: Arc<dyn Storage>, kv: Arc<dyn KvStore>) -> Self
pub fn new(storage: Arc<dyn Storage>, kv: Arc<dyn KvStore>) -> Self
Build a deploy store over a blob storage and a metadata kv.
Sourcepub async fn ready(&self) -> Result<(), DeployError>
pub async fn ready(&self) -> Result<(), DeployError>
Readiness probe: confirm the metadata backend is reachable with a cheap read (a missing key is fine — it still proves the backend answered). The blob backend is exercised per-request rather than probed here.
Sourcepub async fn put_manifest(
&self,
manifest: &Manifest,
) -> Result<String, DeployError>
pub async fn put_manifest( &self, manifest: &Manifest, ) -> Result<String, DeployError>
Store a manifest (idempotent) and return its deployment id.
Sourcepub async fn put_manifest_with(
&self,
manifest: &Manifest,
input: DeployMetaInput,
) -> Result<String, DeployError>
pub async fn put_manifest_with( &self, manifest: &Manifest, input: DeployMetaInput, ) -> Result<String, DeployError>
Store a manifest (idempotent) and record/refresh its DeployMeta.
created_at is set on first store and preserved across re-deploys of the
same content (so the GC grace window measures true age); sizes are
recomputed from the manifest, and the client-supplied provenance fields
are merged in (a later deploy of identical content can update its source/
message without resetting created_at).
Sourcepub async fn get_meta(
&self,
id: &str,
) -> Result<Option<DeployMeta>, DeployError>
pub async fn get_meta( &self, id: &str, ) -> Result<Option<DeployMeta>, DeployError>
Fetch a deployment’s DeployMeta, if recorded.
Sourcepub async fn get_manifest(
&self,
id: &str,
) -> Result<Option<Manifest>, DeployError>
pub async fn get_manifest( &self, id: &str, ) -> Result<Option<Manifest>, DeployError>
Fetch a manifest by deployment id.
Sourcepub async fn resolve_manifest_id(
&self,
prefix: &str,
) -> Result<Option<String>, DeployError>
pub async fn resolve_manifest_id( &self, prefix: &str, ) -> Result<Option<String>, DeployError>
Resolve a deployment-id prefix to the one full id it uniquely names
(an exact id resolves to itself). Used for the wildcard preview host form
<id>.deploy.<host>, where the id rides as a DNS label — capped at 63
chars, shorter than a full 64-hex content hash — so operators use a
prefix. Returns None if nothing matches; Err(Ambiguous) if the prefix
is not unique (the caller should treat that as not-found).
Sourcepub async fn has_blob(&self, hash: &str) -> Result<bool, DeployError>
pub async fn has_blob(&self, hash: &str) -> Result<bool, DeployError>
Whether a blob with hash is already stored.
Sourcepub async fn missing_blobs(
&self,
manifest: &Manifest,
) -> Result<Vec<String>, DeployError>
pub async fn missing_blobs( &self, manifest: &Manifest, ) -> Result<Vec<String>, DeployError>
The blob hashes from manifest that the store is missing.
Sourcepub async fn put_blob(
&self,
hash: &str,
body: ByteStream,
) -> Result<(), DeployError>
pub async fn put_blob( &self, hash: &str, body: ByteStream, ) -> Result<(), DeployError>
Stream a blob into storage, verifying it hashes to hash.
The bytes are hashed as they pass through to the backend (never fully buffered). A mismatch deletes the partial blob and errors.
Sourcepub async fn open_blob(&self, hash: &str) -> Result<GetObject, DeployError>
pub async fn open_blob(&self, hash: &str) -> Result<GetObject, DeployError>
Open a blob for streaming reads.
Sourcepub async fn open_blob_range(
&self,
hash: &str,
offset: u64,
len: Option<u64>,
) -> Result<GetObject, DeployError>
pub async fn open_blob_range( &self, hash: &str, offset: u64, len: Option<u64>, ) -> Result<GetObject, DeployError>
Open a byte range of a blob for streaming reads (HTTP Range).
Sourcepub async fn get_site_config(
&self,
project: ProjectRef<'_>,
site: &str,
) -> Result<Option<SiteConfig>, DeployError>
pub async fn get_site_config( &self, project: ProjectRef<'_>, site: &str, ) -> Result<Option<SiteConfig>, DeployError>
A site’s SiteConfig, if it has been set. Reads the site/<site>
pointer, then the immutable siteconfig/<hash> body it names.
Sourcepub async fn set_site_config(
&self,
project: ProjectRef<'_>,
site: &str,
config: &SiteConfig,
) -> Result<(), DeployError>
pub async fn set_site_config( &self, project: ProjectRef<'_>, site: &str, config: &SiteConfig, ) -> Result<(), DeployError>
Store a site’s SiteConfig and rebuild its host → site index entries
(so resolve_site_by_host can route by Host).
Content-addressed: the config body is written
once under siteconfig/<hash> (immutable, dedup’d) and the mutable
site/<site> pointer is flipped to it. Only the tiny pointer changes, so
the shared-mode invalidation surface is the pointer, not the body. The
whole change (drop old index, write body, flip pointer, write new index)
commits as one atomic batch.
Host uniqueness (hijack guard): a host — or wildcard suffix — already
mapped to a different site is refused with DeployError::Conflict
rather than silently overwritten. Without this, any site-writer could
point another site’s live domain at their own site (last-writer-wins
takeover). The read-check and the write are serialized by a process-local
lock so they can’t be interleaved across an await. This is airtight on a
single node; a Raft cluster holds it per node, and a cross-node claim race
would additionally need a consensus-level conditional apply — a documented
follow-up, not reachable in the dominant single-node topology.
Sourcepub async fn resolve_site_by_host(
&self,
host: &str,
) -> Result<Option<DomainOwner>, DeployError>
pub async fn resolve_site_by_host( &self, host: &str, ) -> Result<Option<DomainOwner>, DeployError>
Resolve a request Host to its owning (project, site): exact match first,
then wildcard suffixes from most specific to least (so *.example.com
matches a.b.example.com). The index value is a tolerant DomainOwner
(a legacy bare-string value reads as the default project).
Sourcepub async fn all_sites(
&self,
project: ProjectRef<'_>,
) -> Result<Vec<String>, DeployError>
pub async fn all_sites( &self, project: ProjectRef<'_>, ) -> Result<Vec<String>, DeployError>
Every known site name in project, sorted and de-duplicated. A site is
“known” if it has a current deployment, a config, or activation history —
so a configured-but-not-yet-deployed site (or vice versa) still appears.
Backs GET /api/sites. (Broader than list_sites,
which is just the currently-deployed sites the scheduler runs.)
Sourcepub async fn all_sites_all(&self) -> Result<Vec<(String, String)>, DeployError>
pub async fn all_sites_all(&self) -> Result<Vec<(String, String)>, DeployError>
Every (project, site) known across all projects — the cross-project
fan-out backing the scheduler and admin surfaces. Discovers the project set
by scanning [keys::PROJECT_ROOT], then unions each project’s all_sites.
Sourcepub async fn discover_projects(&self) -> Result<Vec<String>, DeployError>
pub async fn discover_projects(&self) -> Result<Vec<String>, DeployError>
The distinct project names with any record in the store (the segment after
[keys::PROJECT_ROOT]). Independent of whether a projectmeta/<name>
pointer exists, so a fan-out reaches projects created only implicitly (e.g.
pre-migration data re-keyed under default).
Sourcepub async fn put_function(
&self,
project: ProjectRef<'_>,
f: &Function,
) -> Result<(), DeployError>
pub async fn put_function( &self, project: ProjectRef<'_>, f: &Function, ) -> Result<(), DeployError>
Store a top-level function’s record (its versions, active, aliases).
Sourcepub async fn get_function(
&self,
project: ProjectRef<'_>,
name: &str,
) -> Result<Option<Function>, DeployError>
pub async fn get_function( &self, project: ProjectRef<'_>, name: &str, ) -> Result<Option<Function>, DeployError>
Load a stored function record, if any.
Sourcepub async fn list_stored_functions(
&self,
project: ProjectRef<'_>,
) -> Result<Vec<Function>, DeployError>
pub async fn list_stored_functions( &self, project: ProjectRef<'_>, ) -> Result<Vec<Function>, DeployError>
List all stored (top-level) functions in project.
Only the …/functions/<name> meta keys are function records; the
…/functions/<name>/{versions,alias,triggers,invocations,idem}/… sub-keys
are skipped by requiring the suffix to hold no further /.
Sourcepub async fn delete_function(
&self,
project: ProjectRef<'_>,
name: &str,
) -> Result<bool, DeployError>
pub async fn delete_function( &self, project: ProjectRef<'_>, name: &str, ) -> Result<bool, DeployError>
Delete a stored function. Returns whether it existed. The component blobs
are content-addressed + shared, so they are left to prune.
Sourcepub async fn put_trigger(
&self,
project: ProjectRef<'_>,
function: &str,
trigger: &FunctionTrigger,
) -> Result<(), DeployError>
pub async fn put_trigger( &self, project: ProjectRef<'_>, function: &str, trigger: &FunctionTrigger, ) -> Result<(), DeployError>
Persist (create or replace) a stored trigger on a function.
Sourcepub async fn get_trigger(
&self,
project: ProjectRef<'_>,
function: &str,
id: &str,
) -> Result<Option<FunctionTrigger>, DeployError>
pub async fn get_trigger( &self, project: ProjectRef<'_>, function: &str, id: &str, ) -> Result<Option<FunctionTrigger>, DeployError>
Load one stored trigger, if any.
Sourcepub async fn list_triggers(
&self,
project: ProjectRef<'_>,
function: &str,
) -> Result<Vec<FunctionTrigger>, DeployError>
pub async fn list_triggers( &self, project: ProjectRef<'_>, function: &str, ) -> Result<Vec<FunctionTrigger>, DeployError>
List a function’s stored triggers.
Sourcepub async fn delete_trigger(
&self,
project: ProjectRef<'_>,
function: &str,
id: &str,
) -> Result<bool, DeployError>
pub async fn delete_trigger( &self, project: ProjectRef<'_>, function: &str, id: &str, ) -> Result<bool, DeployError>
Delete a stored trigger. Returns whether it existed.
Sourcepub async fn put_invocation(
&self,
project: ProjectRef<'_>,
inv: &Invocation,
) -> Result<(), DeployError>
pub async fn put_invocation( &self, project: ProjectRef<'_>, inv: &Invocation, ) -> Result<(), DeployError>
Persist (create or update) an invocation record.
Sourcepub async fn get_invocation(
&self,
project: ProjectRef<'_>,
function: &str,
id: &str,
) -> Result<Option<Invocation>, DeployError>
pub async fn get_invocation( &self, project: ProjectRef<'_>, function: &str, id: &str, ) -> Result<Option<Invocation>, DeployError>
Load one invocation record, if any.
Sourcepub async fn list_invocations(
&self,
project: ProjectRef<'_>,
function: &str,
) -> Result<Vec<Invocation>, DeployError>
pub async fn list_invocations( &self, project: ProjectRef<'_>, function: &str, ) -> Result<Vec<Invocation>, DeployError>
List a function’s invocation records (queue scan / poll listing).
Sourcepub async fn put_idempotency(
&self,
project: ProjectRef<'_>,
function: &str,
key: &str,
invocation_id: &str,
) -> Result<(), DeployError>
pub async fn put_idempotency( &self, project: ProjectRef<'_>, function: &str, key: &str, invocation_id: &str, ) -> Result<(), DeployError>
Bind an idempotency key to an invocation id (the dedup pointer). The value is the raw invocation id.
Sourcepub async fn get_idempotency(
&self,
project: ProjectRef<'_>,
function: &str,
key: &str,
) -> Result<Option<String>, DeployError>
pub async fn get_idempotency( &self, project: ProjectRef<'_>, function: &str, key: &str, ) -> Result<Option<String>, DeployError>
Resolve an idempotency key to its invocation id, if one was recorded.
Sourcepub async fn get_metering(
&self,
project: ProjectRef<'_>,
function: &str,
) -> Result<Option<Metering>, DeployError>
pub async fn get_metering( &self, project: ProjectRef<'_>, function: &str, ) -> Result<Option<Metering>, DeployError>
The usage aggregate for a function, if any has been recorded.
Sourcepub async fn put_metering(
&self,
project: ProjectRef<'_>,
metering: &Metering,
) -> Result<(), DeployError>
pub async fn put_metering( &self, project: ProjectRef<'_>, metering: &Metering, ) -> Result<(), DeployError>
Persist a function’s usage aggregate.
Sourcepub async fn list_metering(
&self,
project: ProjectRef<'_>,
) -> Result<Vec<Metering>, DeployError>
pub async fn list_metering( &self, project: ProjectRef<'_>, ) -> Result<Vec<Metering>, DeployError>
List every function’s usage aggregate in project (the functions usage
fan-out).
Sourcepub async fn put_managed_notification(
&self,
project: ProjectRef<'_>,
record: &ManagedNotification,
) -> Result<(), DeployError>
pub async fn put_managed_notification( &self, project: ProjectRef<'_>, record: &ManagedNotification, ) -> Result<(), DeployError>
Record the cloud notification pipeline provisioned for a function’s blob-change trigger, so it can be retracted later.
Sourcepub async fn get_managed_notification(
&self,
project: ProjectRef<'_>,
function: &str,
prefix: &str,
) -> Result<Option<ManagedNotification>, DeployError>
pub async fn get_managed_notification( &self, project: ProjectRef<'_>, function: &str, prefix: &str, ) -> Result<Option<ManagedNotification>, DeployError>
The notification ledger entry for (function, prefix), if any.
Sourcepub async fn list_managed_notifications(
&self,
project: ProjectRef<'_>,
function: &str,
) -> Result<Vec<ManagedNotification>, DeployError>
pub async fn list_managed_notifications( &self, project: ProjectRef<'_>, function: &str, ) -> Result<Vec<ManagedNotification>, DeployError>
All notification ledger entries for a function.
Sourcepub async fn remove_managed_notification(
&self,
project: ProjectRef<'_>,
function: &str,
prefix: &str,
) -> Result<(), DeployError>
pub async fn remove_managed_notification( &self, project: ProjectRef<'_>, function: &str, prefix: &str, ) -> Result<(), DeployError>
Drop a notification ledger entry (after its resources are retracted).
Sourcepub async fn put_workflow(
&self,
project: ProjectRef<'_>,
workflow: &Workflow,
) -> Result<(), DeployError>
pub async fn put_workflow( &self, project: ProjectRef<'_>, workflow: &Workflow, ) -> Result<(), DeployError>
Persist a workflow definition.
Sourcepub async fn get_workflow(
&self,
project: ProjectRef<'_>,
name: &str,
) -> Result<Option<Workflow>, DeployError>
pub async fn get_workflow( &self, project: ProjectRef<'_>, name: &str, ) -> Result<Option<Workflow>, DeployError>
Load a workflow definition, if any.
Sourcepub async fn list_workflows(
&self,
project: ProjectRef<'_>,
) -> Result<Vec<Workflow>, DeployError>
pub async fn list_workflows( &self, project: ProjectRef<'_>, ) -> Result<Vec<Workflow>, DeployError>
List all workflow definitions in project (skips the
…/workflows/<name>/runs/… sub-keys by requiring the suffix to hold no
further /).
Sourcepub async fn delete_workflow(
&self,
project: ProjectRef<'_>,
name: &str,
) -> Result<bool, DeployError>
pub async fn delete_workflow( &self, project: ProjectRef<'_>, name: &str, ) -> Result<bool, DeployError>
Delete a workflow definition. Returns whether it existed. Runs are left in
place (terminal history); prune removes them.
Sourcepub async fn put_workflow_run(
&self,
project: ProjectRef<'_>,
run: &WorkflowRun,
) -> Result<(), DeployError>
pub async fn put_workflow_run( &self, project: ProjectRef<'_>, run: &WorkflowRun, ) -> Result<(), DeployError>
Persist (create or update) a workflow run.
Sourcepub async fn get_workflow_run(
&self,
project: ProjectRef<'_>,
workflow: &str,
id: &str,
) -> Result<Option<WorkflowRun>, DeployError>
pub async fn get_workflow_run( &self, project: ProjectRef<'_>, workflow: &str, id: &str, ) -> Result<Option<WorkflowRun>, DeployError>
Load one workflow run, if any.
Sourcepub async fn list_workflow_runs(
&self,
project: ProjectRef<'_>,
workflow: &str,
) -> Result<Vec<WorkflowRun>, DeployError>
pub async fn list_workflow_runs( &self, project: ProjectRef<'_>, workflow: &str, ) -> Result<Vec<WorkflowRun>, DeployError>
List a workflow’s runs (the executor drain scan / poll listing).
Sourcepub async fn get_domain_verification(
&self,
project: ProjectRef<'_>,
site: &SiteName,
host: &str,
) -> Result<Option<DomainVerification>, DeployError>
pub async fn get_domain_verification( &self, project: ProjectRef<'_>, site: &SiteName, host: &str, ) -> Result<Option<DomainVerification>, DeployError>
The ownership-verification challenge for (site, host), if one exists.
Sourcepub async fn list_domain_verifications(
&self,
project: ProjectRef<'_>,
site: &SiteName,
) -> Result<Vec<DomainVerification>, DeployError>
pub async fn list_domain_verifications( &self, project: ProjectRef<'_>, site: &SiteName, ) -> Result<Vec<DomainVerification>, DeployError>
All ownership challenges for site (pending and verified), by host.
Sourcepub async fn list_all_domain_verifications(
&self,
) -> Result<Vec<(String, String, DomainVerification)>, DeployError>
pub async fn list_all_domain_verifications( &self, ) -> Result<Vec<(String, String, DomainVerification)>, DeployError>
Every ownership challenge across all projects, each paired with its
owning (project, site) — the enumeration behind the auto-complete
reconcile loop. Fans out over discover_projects
and scans each project’s domainverify/ keyspace, so a challenge started
before a site’s first publish (its site isn’t in
all_sites yet) is still found and can self-heal.
Sourcepub async fn find_pending_http_challenge(
&self,
host: &str,
token: &str,
now_unix: u64,
) -> Result<Option<DomainVerification>, DeployError>
pub async fn find_pending_http_challenge( &self, host: &str, token: &str, now_unix: u64, ) -> Result<Option<DomainVerification>, DeployError>
Find a pending HTTP ownership challenge matching (host, token)
across every project/site — the lookup behind the self-serve edge route
/.well-known/boatramp-domain-verification/<token>. Matches on the
normalized host, the HTTP method, an exact token match, and a non-expired
challenge (now_unix gates the TTL), so a host pointed at this server can
prove ownership before it is attached and deployed — closing the
verify-before-attach chicken-and-egg. Returns the challenge so the caller
can echo its token back.
Sourcepub async fn get_managed_dns(
&self,
project: ProjectRef<'_>,
site: &SiteName,
host: &str,
) -> Result<Option<ManagedDns>, DeployError>
pub async fn get_managed_dns( &self, project: ProjectRef<'_>, site: &SiteName, host: &str, ) -> Result<Option<ManagedDns>, DeployError>
The managed-DNS ledger for (site, host), if boatramp has pointed it.
Sourcepub async fn set_managed_dns(
&self,
project: ProjectRef<'_>,
site: &SiteName,
ledger: &ManagedDns,
) -> Result<(), DeployError>
pub async fn set_managed_dns( &self, project: ProjectRef<'_>, site: &SiteName, ledger: &ManagedDns, ) -> Result<(), DeployError>
Record (create/replace) the managed-DNS ledger entry for a host.
Sourcepub async fn remove_managed_dns(
&self,
project: ProjectRef<'_>,
site: &SiteName,
host: &str,
) -> Result<(), DeployError>
pub async fn remove_managed_dns( &self, project: ProjectRef<'_>, site: &SiteName, host: &str, ) -> Result<(), DeployError>
Drop a host’s managed-DNS ledger entry (after its records are retracted).
Sourcepub async fn list_managed_dns(
&self,
project: ProjectRef<'_>,
site: &SiteName,
) -> Result<Vec<ManagedDns>, DeployError>
pub async fn list_managed_dns( &self, project: ProjectRef<'_>, site: &SiteName, ) -> Result<Vec<ManagedDns>, DeployError>
All managed-DNS ledger entries for site (the reconcile sweep reads these
to retract records whose host is no longer attached).
Sourcepub async fn start_domain_verification(
&self,
project: ProjectRef<'_>,
site: &SiteName,
host: &str,
method: VerificationMethod,
now_unix: u64,
) -> Result<DomainVerification, DeployError>
pub async fn start_domain_verification( &self, project: ProjectRef<'_>, site: &SiteName, host: &str, method: VerificationMethod, now_unix: u64, ) -> Result<DomainVerification, DeployError>
Start (or restart) an ownership challenge for (site, host).
Returns the existing challenge if one is already pending under the same
method (so re-running domain add shows the same token instead of
invalidating an in-progress setup); otherwise mints a fresh one. A
challenge that’s already verified is returned untouched.
Sourcepub async fn is_domain_verified(
&self,
project: ProjectRef<'_>,
site: &SiteName,
host: &str,
) -> Result<bool, DeployError>
pub async fn is_domain_verified( &self, project: ProjectRef<'_>, site: &SiteName, host: &str, ) -> Result<bool, DeployError>
Whether (site, host) has a confirmed ownership challenge.
Sourcepub async fn mark_domain_verified(
&self,
project: ProjectRef<'_>,
site: &SiteName,
host: &str,
) -> Result<DomainVerification, DeployError>
pub async fn mark_domain_verified( &self, project: ProjectRef<'_>, site: &SiteName, host: &str, ) -> Result<DomainVerification, DeployError>
Mark (site, host)’s challenge verified and persist it. Errors if no
challenge has been started.
Sourcepub async fn remove_domain_verification(
&self,
project: ProjectRef<'_>,
site: &SiteName,
host: &str,
) -> Result<bool, DeployError>
pub async fn remove_domain_verification( &self, project: ProjectRef<'_>, site: &SiteName, host: &str, ) -> Result<bool, DeployError>
Drop the verification record for (site, host) (when detaching a host).
Returns whether one existed.
Sourcepub async fn attach_verified_domain(
&self,
project: ProjectRef<'_>,
site: &SiteName,
host: &str,
) -> Result<SiteConfig, DeployError>
pub async fn attach_verified_domain( &self, project: ProjectRef<'_>, site: &SiteName, host: &str, ) -> Result<SiteConfig, DeployError>
Attach a verified host to the site’s SiteConfig so it routes by
Host and becomes eligible for ACME. The host’s kind is inferred:
a *.-prefixed host is a wildcard; otherwise it becomes the primary if
the site has none, else an alias.
Refuses an unverified host — this is the server-enforced gate that keeps
unowned domains out of routing and out of cert issuance. (The wildcard /
primary base name is verified; see normalize_host.)
Sourcepub async fn set_alias(
&self,
project: ProjectRef<'_>,
site: &str,
name: &str,
id: &str,
) -> Result<(), DeployError>
pub async fn set_alias( &self, project: ProjectRef<'_>, site: &str, name: &str, id: &str, ) -> Result<(), DeployError>
Point a named alias (staging, preview-pr-42, …) at a deployment id.
Like activate, this refuses a deployment whose blobs
are not all present, so an alias never resolves to an incomplete deploy.
Aliased deployments are retention-protected from garbage collection.
Sourcepub async fn get_alias(
&self,
project: ProjectRef<'_>,
site: &str,
name: &str,
) -> Result<Option<String>, DeployError>
pub async fn get_alias( &self, project: ProjectRef<'_>, site: &str, name: &str, ) -> Result<Option<String>, DeployError>
Resolve a named alias to its deployment id, if set.
Sourcepub async fn remove_alias(
&self,
project: ProjectRef<'_>,
site: &str,
name: &str,
) -> Result<bool, DeployError>
pub async fn remove_alias( &self, project: ProjectRef<'_>, site: &str, name: &str, ) -> Result<bool, DeployError>
Remove a named alias; returns whether one existed.
Sourcepub async fn list_aliases(
&self,
project: ProjectRef<'_>,
site: &str,
) -> Result<BTreeMap<String, String>, DeployError>
pub async fn list_aliases( &self, project: ProjectRef<'_>, site: &str, ) -> Result<BTreeMap<String, String>, DeployError>
All of a site’s named aliases as name → deployment id, sorted by name.
Sourcepub async fn put_token_meta(&self, meta: &TokenMeta) -> Result<(), DeployError>
pub async fn put_token_meta(&self, meta: &TokenMeta) -> Result<(), DeployError>
Store metadata for an issued token (authz/tokens/<id>). The
token itself is never stored — only this record, for token ls.
Minting needs the root private key, so it happens in the
caller (the API route / CLI), which then records the metadata here.
Sourcepub async fn list_token_meta(&self) -> Result<Vec<TokenMeta>, DeployError>
pub async fn list_token_meta(&self) -> Result<Vec<TokenMeta>, DeployError>
List metadata for all issued, non-revoked tokens.
Sourcepub async fn revoke_token(
&self,
id_or_prefix: &str,
) -> Result<bool, DeployError>
pub async fn revoke_token( &self, id_or_prefix: &str, ) -> Result<bool, DeployError>
Revoke an issued token by its revocation id (or a unique id prefix):
write the authz/revoked/<id> marker and drop its metadata. Returns
whether a matching token was found. The marker makes every node deny the
token (and its attenuations) on the next request.
Sourcepub async fn bootstrap_consumed(
&self,
secret_hash: &str,
) -> Result<bool, DeployError>
pub async fn bootstrap_consumed( &self, secret_hash: &str, ) -> Result<bool, DeployError>
Whether a first-token bootstrap secret (identified by its SHA-256 hex) has already been redeemed. The marker persists, so a spent secret stays spent across restarts; rotating the secret yields a fresh hash that re-enables bootstrap (the recovery path).
Sourcepub async fn mark_bootstrap_consumed(
&self,
secret_hash: &str,
) -> Result<(), DeployError>
pub async fn mark_bootstrap_consumed( &self, secret_hash: &str, ) -> Result<(), DeployError>
Mark a bootstrap secret (by SHA-256 hex) consumed — single-use.
Sourcepub async fn get_authz_policy(&self) -> Result<Option<AuthzPolicy>, DeployError>
pub async fn get_authz_policy(&self) -> Result<Option<AuthzPolicy>, DeployError>
Read the stored RBAC AuthzPolicy (authz/policy), or None when the
built-in default is in effect.
Sourcepub async fn set_authz_policy(
&self,
policy: &AuthzPolicy,
) -> Result<(), DeployError>
pub async fn set_authz_policy( &self, policy: &AuthzPolicy, ) -> Result<(), DeployError>
Store the RBAC AuthzPolicy. The caller validates it first (the server
route compiles it before storing); a write rides the existing cache
invalidation so every node picks it up.
Sourcepub async fn add_root_anchor(&self, pubkey: &str) -> Result<(), DeployError>
pub async fn add_root_anchor(&self, pubkey: &str) -> Result<(), DeployError>
Trust an additional root anchor (auth rotate-root): a TokenPublicKey
(alg:hex) accepted alongside the configured primary root, for a
make-before-break rotation. Replicated to every node through the control
plane, so no per-node edit is needed.
Sourcepub async fn remove_root_anchor(&self, pubkey: &str) -> Result<(), DeployError>
pub async fn remove_root_anchor(&self, pubkey: &str) -> Result<(), DeployError>
Retire a previously-added root anchor (the old key, after propagation).
Sourcepub async fn list_root_anchors(&self) -> Result<Vec<String>, DeployError>
pub async fn list_root_anchors(&self) -> Result<Vec<String>, DeployError>
The currently-trusted extra root anchors (the alg:hex public keys).
Sourcepub async fn daemon_config_generation(
&self,
) -> Result<Option<String>, DeployError>
pub async fn daemon_config_generation( &self, ) -> Result<Option<String>, DeployError>
The active daemon-config generation (the daemon/current hash), if any.
This is the value nodes report so an operator can confirm convergence.
Sourcepub async fn get_daemon_config(
&self,
) -> Result<Option<DaemonConfig>, DeployError>
pub async fn get_daemon_config( &self, ) -> Result<Option<DaemonConfig>, DeployError>
The active dynamic daemon config, if any (None = none set ⇒ the server
runs on the pure file baseline).
Sourcepub async fn daemon_config_history(&self) -> Result<Vec<String>, DeployError>
pub async fn daemon_config_history(&self) -> Result<Vec<String>, DeployError>
The rollback history (oldest → newest prior generation hashes; excludes the current generation).
Sourcepub async fn set_daemon_config(
&self,
config: &DaemonConfig,
) -> Result<String, DeployError>
pub async fn set_daemon_config( &self, config: &DaemonConfig, ) -> Result<String, DeployError>
Store a new daemon config: write the content-addressed body, push the
current generation onto the bounded history, and flip the daemon/current
pointer — all as one atomic batch. The caller validates first (the
server route runs DaemonConfig::validate
before this). Returns the new generation hash.
Sourcepub async fn rollback_daemon_config(
&self,
) -> Result<Option<String>, DeployError>
pub async fn rollback_daemon_config( &self, ) -> Result<Option<String>, DeployError>
Roll back to the previous generation: pop the history and flip the pointer,
atomically. Returns the hash rolled back to, or None if there is no
history. Reverting past the last dynamic config falls back to the file
baseline (which already booted successfully — the known-good floor).
Sourcepub async fn put_compute_spec(
&self,
spec: &ComputeSpec,
) -> Result<String, DeployError>
pub async fn put_compute_spec( &self, spec: &ComputeSpec, ) -> Result<String, DeployError>
Store an immutable, content-addressed ComputeSpec
at computever/<hash> (idempotent), returning its hash.
Sourcepub async fn get_compute_spec(
&self,
hash: &str,
) -> Result<Option<ComputeSpec>, DeployError>
pub async fn get_compute_spec( &self, hash: &str, ) -> Result<Option<ComputeSpec>, DeployError>
Read a compute spec by its content hash.
Sourcepub async fn set_compute_workload(
&self,
project: ProjectRef<'_>,
workload: &ComputeWorkload,
) -> Result<(), DeployError>
pub async fn set_compute_workload( &self, project: ProjectRef<'_>, workload: &ComputeWorkload, ) -> Result<(), DeployError>
Set (replacing) a workload’s desired state at
project/<proj>/compute/<name>. Activation is this pointer write — atomic,
like a deployment’s current.
Sourcepub async fn get_compute_workload(
&self,
project: ProjectRef<'_>,
name: &str,
) -> Result<Option<ComputeWorkload>, DeployError>
pub async fn get_compute_workload( &self, project: ProjectRef<'_>, name: &str, ) -> Result<Option<ComputeWorkload>, DeployError>
Read a workload’s desired state.
Sourcepub async fn list_compute_workloads(
&self,
project: ProjectRef<'_>,
) -> Result<Vec<ComputeWorkload>, DeployError>
pub async fn list_compute_workloads( &self, project: ProjectRef<'_>, ) -> Result<Vec<ComputeWorkload>, DeployError>
List a project’s compute workloads’ desired state.
Sourcepub async fn list_compute_workloads_all(
&self,
) -> Result<Vec<(String, ComputeWorkload)>, DeployError>
pub async fn list_compute_workloads_all( &self, ) -> Result<Vec<(String, ComputeWorkload)>, DeployError>
List every compute workload across all projects, each paired with its owning project — the cross-project fan-out the scheduler runs.
Sourcepub async fn delete_compute_workload(
&self,
project: ProjectRef<'_>,
name: &str,
) -> Result<bool, DeployError>
pub async fn delete_compute_workload( &self, project: ProjectRef<'_>, name: &str, ) -> Result<bool, DeployError>
Remove a workload’s desired state (the executor then stops its replicas). Returns whether one existed.
Sourcepub async fn set_replica_state(
&self,
project: ProjectRef<'_>,
state: &ObservedInstance,
) -> Result<(), DeployError>
pub async fn set_replica_state( &self, project: ProjectRef<'_>, state: &ObservedInstance, ) -> Result<(), DeployError>
Persist a replica’s observed state at
project/<proj>/compute_state/<workload>/<replica> (the reconcile loop’s
record + the gateway’s upstream source).
Sourcepub async fn list_replica_states(
&self,
project: ProjectRef<'_>,
workload: &str,
) -> Result<Vec<ObservedInstance>, DeployError>
pub async fn list_replica_states( &self, project: ProjectRef<'_>, workload: &str, ) -> Result<Vec<ObservedInstance>, DeployError>
List a workload’s observed replica states.
Sourcepub async fn list_all_replica_states(
&self,
) -> Result<Vec<ObservedInstance>, DeployError>
pub async fn list_all_replica_states( &self, ) -> Result<Vec<ObservedInstance>, DeployError>
List all observed replica states across every project’s workloads (the
gateway’s dynamic-pool source). Fans out over
discover_projects.
Sourcepub async fn delete_replica_state(
&self,
project: ProjectRef<'_>,
workload: &str,
replica: u32,
) -> Result<(), DeployError>
pub async fn delete_replica_state( &self, project: ProjectRef<'_>, workload: &str, replica: u32, ) -> Result<(), DeployError>
Remove a replica’s observed state.
Sourcepub async fn put_project(&self, p: &Project) -> Result<String, DeployError>
pub async fn put_project(&self, p: &Project) -> Result<String, DeployError>
Create or update a project: store its content-addressed spec body (idempotent)
and flip the projectmeta/<name> pointer to it, recording the prior pointer in
the history ring for rollback.
Sourcepub fn default_project_record() -> Project
pub fn default_project_record() -> Project
The canonical record for the reserved default project — the single source
of its shape, shared by Self::ensure_default_project, the migration’s
EnsureDefaultProject step, and the reader-side backstop in
Self::get_project / Self::list_projects.
Sourcepub async fn ensure_default_project(&self) -> Result<bool, DeployError>
pub async fn ensure_default_project(&self) -> Result<bool, DeployError>
Idempotently materialize the reserved default project’s entity record, so
project ls / project show default reflect it on a fresh install just as
they do on a migrated store. Presence-checked and content-addressed, so it is
safe to call on every boot; in cluster mode the write forwards to the leader
and concurrent callers converge (identical body). Returns whether it created
the record. The reserved name is defined to always exist — this makes that
true in the store, not only in the reader backstop below.
Sourcepub async fn project_exists(&self, name: &str) -> Result<bool, DeployError>
pub async fn project_exists(&self, name: &str) -> Result<bool, DeployError>
Cheap existence check for a project entity — whether its projectmeta/<name>
pointer is present. Used by the project-scope middleware to reject an
operation on a project that was never created (rather than silently
manufacturing a ghost). The reserved default always exists.
Sourcepub async fn get_project(
&self,
name: &str,
) -> Result<Option<Project>, DeployError>
pub async fn get_project( &self, name: &str, ) -> Result<Option<Project>, DeployError>
Load a project’s active version, if it exists.
Sourcepub async fn list_projects(&self) -> Result<Vec<Project>, DeployError>
pub async fn list_projects(&self) -> Result<Vec<Project>, DeployError>
Every declared project, sorted by name. (A project may also exist only
implicitly as a project/<name>/ key prefix without a projectmeta
pointer — see discover_projects for that union.)
Sourcepub async fn delete_project(&self, name: &str) -> Result<bool, DeployError>
pub async fn delete_project(&self, name: &str) -> Result<bool, DeployError>
Delete a project’s pointer + history. Refuses (with DeployError::Conflict)
while the project still owns any resource — a project is deleted only once
empty, so a stray site/function/compute can’t be silently orphaned. The
content-addressed spec bodies are shared + left to prune. Deleting the
reserved default project is refused outright.
Sourcepub async fn activate(
&self,
project: ProjectRef<'_>,
site: &str,
id: &str,
) -> Result<(), DeployError>
pub async fn activate( &self, project: ProjectRef<'_>, site: &str, id: &str, ) -> Result<(), DeployError>
Atomically point site at deployment id.
Refuses to activate a deployment whose blobs are not all present.
Sourcepub async fn history(
&self,
project: ProjectRef<'_>,
site: &str,
) -> Result<Vec<HistoryEntry>, DeployError>
pub async fn history( &self, project: ProjectRef<'_>, site: &str, ) -> Result<Vec<HistoryEntry>, DeployError>
A site’s activation history, most recent first.
Sourcepub async fn deployments(
&self,
project: ProjectRef<'_>,
site: &str,
) -> Result<DeploymentList, DeployError>
pub async fn deployments( &self, project: ProjectRef<'_>, site: &str, ) -> Result<DeploymentList, DeployError>
A site’s current deployment plus its activation history, each history
entry joined with its DeployMeta provenance (when recorded).
Sourcepub async fn collect_garbage(
&self,
prune: bool,
) -> Result<GcReport, DeployError>
pub async fn collect_garbage( &self, prune: bool, ) -> Result<GcReport, DeployError>
Garbage-collect deployments unreachable from any site’s current
pointer, alias, or retained history, and the blobs no surviving
deployment references.
Equivalent to collect_garbage_with with
default options (keep all history, no grace window).
Sourcepub async fn collect_garbage_with(
&self,
prune: bool,
opts: GcOptions,
) -> Result<GcReport, DeployError>
pub async fn collect_garbage_with( &self, prune: bool, opts: GcOptions, ) -> Result<GcReport, DeployError>
Garbage-collect under an explicit retention policy and grace window.
A manifest survives if it is reachable (see
live_deployment_ids) or was first seen
within opts.grace_secs — the latter protects an in-flight deploy whose
manifest is stored and blobs are uploading but which is not yet
activated. A blob survives if any surviving manifest references it.
With prune == false nothing is deleted; the GcReport describes what
would be removed.
Sourcepub async fn scrub_blobs(&self) -> Result<ScrubReport, DeployError>
pub async fn scrub_blobs(&self) -> Result<ScrubReport, DeployError>
Verify every stored blob still hashes to its key — an integrity scrub that detects bit-rot or tampering. Each blob is streamed through a hasher (never fully buffered); read-only (never deletes). The serving path can’t reject a corrupt blob without buffering, so this verification is performed offline.
Sourcepub fn invalidate_cache_keys(&self, keys: &[String])
pub fn invalidate_cache_keys(&self, keys: &[String])
Drop these keys from the control-plane KV’s local cache (shared-mode
push invalidation). A Cloudflare DO /
Queue (or any pusher) calls this — via the /api/cache/invalidate
endpoint — when a peer changed those keys, for real-time invalidation
without waiting on the poll interval. A no-op on an uncached/Raft store.
Sourcepub fn invalidate_cache(&self)
pub fn invalidate_cache(&self)
Drop the entire control-plane KV cache (the coarse fallback / SIGHUP
equivalent over HTTP).
Sourcepub async fn cert_status(&self) -> Result<Vec<CertStatus>, DeployError>
pub async fn cert_status(&self) -> Result<Vec<CertStatus>, DeployError>
The key-free status (domain + expiry) of every cluster-managed cert in
the control plane (cert/<domain>). Empty when certs
live in a file cache instead (single-node acme). Never returns key
material. Sorted by domain.
Sourcepub async fn list_sites(
&self,
project: ProjectRef<'_>,
) -> Result<Vec<String>, DeployError>
pub async fn list_sites( &self, project: ProjectRef<'_>, ) -> Result<Vec<String>, DeployError>
Every site in project that has a current deployment (i.e. a
project/<proj>/current/<site> pointer). Used by the background scheduler
to find which sites’ consumers and crons to run.
Sourcepub async fn list_sites_all(&self) -> Result<Vec<(String, String)>, DeployError>
pub async fn list_sites_all(&self) -> Result<Vec<(String, String)>, DeployError>
Every (project, site) with a current deployment across all projects —
the cross-project fan-out for the scheduler/operator.
Sourcepub async fn delete_site(
&self,
project: ProjectRef<'_>,
site: &str,
) -> Result<(), DeployError>
pub async fn delete_site( &self, project: ProjectRef<'_>, site: &str, ) -> Result<(), DeployError>
Delete a site and its routing/config state (the Kubernetes operator’s
Site finalizer). Removes the config pointer, the current-deployment
pointer, activation history, aliases, the domain-routing entries the site
owns (so its hosts free up), and any pending domain verifications — all
within project. The content-addressed deployment manifests + blobs are
shared and left to prune. Idempotent (deleting an absent site is a no-op).
Sourcepub async fn current_id(
&self,
project: ProjectRef<'_>,
site: &str,
) -> Result<Option<String>, DeployError>
pub async fn current_id( &self, project: ProjectRef<'_>, site: &str, ) -> Result<Option<String>, DeployError>
The deployment id currently serving site, if any.
Sourcepub async fn current_manifest(
&self,
project: ProjectRef<'_>,
site: &str,
) -> Result<Option<Manifest>, DeployError>
pub async fn current_manifest( &self, project: ProjectRef<'_>, site: &str, ) -> Result<Option<Manifest>, DeployError>
The manifest currently serving site, if any.
Sourcepub async fn resolve(
&self,
project: ProjectRef<'_>,
site: &str,
path: &str,
) -> Result<Option<FileEntry>, DeployError>
pub async fn resolve( &self, project: ProjectRef<'_>, site: &str, path: &str, ) -> Result<Option<FileEntry>, DeployError>
Resolve a request path against site’s current deployment.
Applies a directory-index fallback: an empty/trailing-slash path, or a
path with no matching file, falls back to <path>/index.html.
Trait Implementations§
Source§impl Clone for DeployStore
impl Clone for DeployStore
Source§fn clone(&self) -> DeployStore
fn clone(&self) -> DeployStore
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl LedgerSink for DeployStore
The real ledger is the control-plane store.
impl LedgerSink for DeployStore
The real ledger is the control-plane store.
The blob-notify ledger is project-scoped like every function record. This seam
carries no project, so it targets [ProjectRef::DEFAULT] — correct while
functions live under the default project; threading a caller-supplied project
through the LedgerSink trait is a Step-7 follow-up (per-project blob triggers).
Source§fn put<'life0, 'life1, 'async_trait>(
&'life0 self,
record: &'life1 ManagedNotification,
) -> Pin<Box<dyn Future<Output = Result<(), ProvisionError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn put<'life0, 'life1, 'async_trait>(
&'life0 self,
record: &'life1 ManagedNotification,
) -> Pin<Box<dyn Future<Output = Result<(), ProvisionError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn delete<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
function: &'life1 str,
prefix: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), ProvisionError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn delete<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
function: &'life1 str,
prefix: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), ProvisionError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
(function, prefix).