docs: consolidate design documentation and standardize crate English

This commit is contained in:
2026-10-12 14:58:00 +09:00
parent a633a53274
commit 4efb0ace1f
404 changed files with 4556 additions and 11654 deletions
+11
View File
@@ -0,0 +1,11 @@
# workspace-server
Backend that manages persistent Workspace resources and authorization and provides an HTTP API. Coordinates Ticket, Objective, and Worker assignments, Workdir links, and Backend Jobs. Runtime and the controller own Worker execution state and input admission; this crate implements neither the product CLI nor the execution engine.
## Design entry points
- [`server`] — HTTP admission and resource operation coordination
- [`store`] / [`authority`] — SQLite persistence and Workspace resource projections
- [`hosts`] / [`worker_source`] — Runtime delegation and request source verification
- [`backend_job`] — Immutable input, attempt, and structured result boundaries
- [`workspace_catalog`] — Workspace creation and replay contracts
+9
View File
@@ -1,3 +1,12 @@
//! Resolves Backend request actors from human credentials.
//!
//! User identifies the human and Account the Workspace owner; request actors retain both.
//! The store resolves valid API tokens or browser sessions, checking expiry and User existence.
//! Tokens are matched by hash; session cookies use HttpOnly/SameSite.
//! This resolution does not authorize individual Workspace resources. Server admission points
//! and domain services check ownership, Origin, and operation permissions. worker_source
//! separately verifies Runtime signing proofs.
use axum::http::{HeaderMap, header};
use chrono::{DateTime, Duration, Utc};
pub use server_api::{ActorAuthMethod, AuthPublicConfig, AuthenticatedUser, RequestActor};
+14
View File
@@ -1,3 +1,17 @@
//! Projects Workspace Tickets, Objectives, and Memory from domain records to API resources.
//!
//! Normal Backend reads use Workspace-scoped SQLite/domain authority, not a Ticket backend
//! chosen from Worker cwd or legacy repository file layouts. The ticket crate owns Ticket state,
//! relations, and content; the Workspace store owns assignments and Runtime Worker links.
//! Builds bounded detail, thread, relation, assignment, and evidence projections, not full
//! execution sessions as substitute records for domain decisions.
//!
//! Unobservable open MR sources are unknown; past review refs do not imply current commits.
//! Evidence filters use current projections excluding closed MRs: commit requires a settled source;
//! approved_review requires approval tied to the current Ticket content digest and all target MR
//! sources/results. Merged MRs use stored integration evidence, so provider outages alone do not
//! invalidate approval.
use std::{path::PathBuf, sync::Arc};
#[cfg(test)]
+32 -5
View File
@@ -1,9 +1,36 @@
//! Durable Backend-owned jobs executed by ordinary Runtime-managed Workers.
//! Backend-owned Jobs with fixed input and execution limits.
//!
//! A job is durable intent. An attempt binds that intent to one dedicated
//! Worker, and a result is accepted only through the fenced structured-result
//! API below. Runtime lifecycle and final prose are deliberately not success
//! authority.
//! Jobs retain immutable input and final results. Each attempt binds one trial to a dedicated
//! Runtime Worker, input digest, tracked submission identity, and deadline. Requesting and
//! notification Workers are sources and destinations, not parents; stopping or removing them
//! does not cancel the Job. Worker retention and execution lifecycle follow existing Runtime
//! and Workspace resource management.
//!
//! # Replay and reevaluation
//!
//! Replaying the same Job ID and fingerprint returns the current attempt; ID reuse with different
//! input is rejected. Attempts without execution slots remain durably reserved; dispatch advances
//! on completion and restart. Only explicit reevaluation adds attempts. The store checks confirmed
//! failure, remaining attempt budget, completed cleanup of prior attempt Workers, and no occupancy
//! by other Jobs. Unknown execution outcomes are not rerun as new attempts.
//!
//! Serialization-key resource conflicts return the original immutable request as resource_reused.
//! This does not mean new input was processed. Pending/unknown Jobs and unfinished cleanup
//! retain resource occupancy, distinct from replay of an identical request.
//!
//! # Structured results and notifications
//!
//! Result admission matches the authenticated Worker, Workspace, Job, current attempt, input
//! digest, and tracked run, then stores bounded JSON. Identical result replay is idempotent;
//! differing results and stale attempts are rejected. Final prose, Idle, Stopped, and successful
//! model calls are not evidence of Job success. Submission authority comes from the Job binding
//! fixed by the Host at creation/Restore, not a Profile name or purpose alone.
//!
//! Notifications have delivery records separate from results. After restart, unknown deliveries
//! are retried with the same tracked notification ID. Results survive stopped/missing destinations
//! without rerunning the model. Execution recovery matches observable Workers and tracked
//! submissions; lost evidence leaves the outcome unknown. Exactly-once execution of all external
//! side effects is not guaranteed.
use serde::{Deserialize, Serialize};
use serde_json::Value;
@@ -1,2 +1,5 @@
//! Backend compatibility facade for the neutral Host storage manager.
//! Compatibility boundary re-exporting shared Host feature storage management to the Backend.
//!
//! The feature-storage crate owns storage registration and migrations. This module adds neither
//! a Backend-specific storage lifecycle nor a separate schema authority.
pub use feature_storage::*;
+14
View File
@@ -1,3 +1,17 @@
//! Adapter delegating Workspace operations to embedded/remote Runtimes.
//!
//! RuntimeRegistry selects execution owners by Runtime/Worker identity and converts typed
//! requests and results. The Server owns Workspace assignments, Workdir links, and retention;
//! Runtime owns execution endpoints and lifecycle settlement. Display names, socket/session
//! paths, and catalog state do not grant operation authority.
//!
//! Remote requests match the selected Workspace binding against current configuration before
//! issuing short-lived capabilities with the current Workspace signing identity. A binding match
//! selects a destination, not proof of authentication. Stale clients with replaced/revoked bindings
//! are rejected. Method, path/query, body digest, permission, and target identity are request-bound;
//! verification follows Runtime's current Workspace trust. Past connection tests are not reused
//! as authentication state.
use crate::Error;
use crate::resource_broker::BackendResourceBroker;
#[cfg(test)]
+1 -5
View File
@@ -1,8 +1,4 @@
//! Local workspace web control plane backend bootstrap.
//!
//! This crate deliberately provides backend building blocks and an HTTP router;
//! it is not the product CLI facade. Tickets and Objectives are served through
//! Backend authority surfaces rather than Worker-local filesystem access.
#![doc = include_str!("../README.md")]
pub mod auth;
pub mod authority;
+62
View File
@@ -1,3 +1,25 @@
//! Workspace HTTP admission and coordination of domain resource operations.
//!
//! The catalog dispatcher acquires a Workspace lifecycle lease and verifies a signing
//! proof or human actor before entering the inner router. Proof verification precedes
//! resource lock waits; a deleting Workspace rejects reads too. Accepted handlers are
//! not reauthenticated merely because the proof expires. Subsequent resource/provider
//! operations follow their owners' current constraints.
//!
//! Shared Worker admission lives in worker_operations; deletion draining lives in
//! workspace_admission. Generated contract routers and registered WS routes define
//! production entry points. Test helpers do not imply unauthenticated production routes.
//!
//! # Tickets and Orchestrators
//!
//! Ticket operations persist through the domain backend. Current Workspace role assignments
//! constrain Worker-origin state decisions. Queue and event notifications do not imply
//! implementation completion. Runtime Worker spawning, Workdir linking, and Ticket assignment
//! use their respective durable operations. Orchestrator backlog attention rereads current
//! Tickets and interested assignments at startup, Restore, and turn end. Subscription snapshots
//! and reconnection are not turn-end events; Running-to-Idle events are handled separately.
//! This coordinates notifications, not a general event queue or worktree layout policy.
use subjektiv::api::*;
mod backend_job_profile;
mod subjektiv_job;
@@ -847,6 +869,13 @@ struct ExternalProviderAuditContext {
attachment_alias: String,
}
/// Workdir session bound to one External provider connection generation.
///
/// Command handles map to provider handles within this session, never a new generation
/// or reconnected provider. Closing on replacement/detach requests cancellation and terminal
/// output confirmation from the old connection; unconfirmed cleanup is not reported as success.
/// Only confirmed provider shutdown can replace per-command confirmation. Reconnection does
/// not prove that missing commands have stopped.
struct ExternalProviderWorkdirSession {
workdir: workdir::Workdir,
connection: Arc<ExternalProviderConnection>,
@@ -2605,6 +2634,13 @@ fn repository_api_rejection(path: &str, status: StatusCode, message: &str) -> Re
// Log here, not only in the inner Workspace router: the catalog dispatcher can
// reject authentication before that router (and its API error logger) is entered.
/// Records outer-dispatcher rejections using the same safe internal diagnostics.
///
/// Claim-derived identities are emitted as claimed hashes. Method, path without query,
/// and Workspace are request metadata with control-character and length limits. The generated
/// request ID identifies this rejection, not a caller ID or cross-service trace. HTTP responses
/// remain generic 401s without proof details. Classification describes this verification result,
/// not the cause or resolution of earlier intermittent 401s.
fn runtime_request_proof_rejection(
method: &str,
path: &str,
@@ -5245,6 +5281,14 @@ impl WorkspaceApi {
Some(summary)
}
/// Binds observation-based Restore intent to a Runtime-owned operation.
///
/// First queries existing owners/receipts without preparation, handling replay and recovery
/// before new-launch eligibility. New intent rereads singleton, Workdir, and External grants
/// to build references. SSH resources are issued only after Runtime admits the same observation
/// token under its operation lock. Replay does not replace saved preparation; incomplete auth
/// preparation remains ReconciliationRequired. Runtime owns lifecycle settlement, while the
/// returned summary comes from current observation.
fn restore_workspace_worker(
&self,
worker: &RuntimeWorkerRef,
@@ -5658,6 +5702,12 @@ fn persist_external_workdir_permissions(
}
}
/// Converts External grants into session capabilities using READ, WRITE, COMMAND levels.
///
/// WRITE includes READ; COMMAND includes WRITE. Arbitrary independent boolean combinations
/// are not permissions: legacy read+command without write is rejected. Provider registration
/// must match the grant's capabilities; Worker attachments intersect permissions with that ceiling.
/// Write scope alone does not create command permission.
fn external_workdir_capabilities(permissions: &str) -> Result<workdir::WorkdirSessionCapabilities> {
match external_workdir_permissions(permissions)?.grant_level() {
Some(server_api::ExternalWorkdirPermissionLevel::Read) => {
@@ -26147,6 +26197,12 @@ async fn post_passkey_registration_options(
}))
}
/// Consumes a stored WebAuthn ceremony and registers only verified credentials.
///
/// Binds the challenge to User, RP, Origin, and stored verifier state, rejecting consumed or
/// expired ceremonies. Browser assertions alone do not create keys or sessions: credentials
/// are saved and browser sessions issued only after webauthn-rs verification succeeds.
/// Login also verifies a stored ceremony.
fn complete_passkey_registration(
api: &ServerAuthApi,
request: PasskeyRegistrationCompleteRequest,
@@ -26485,6 +26541,12 @@ fn approve_device_login(
})
}
/// Returns the API token generated by browser approval to the device client.
///
/// Pending and expired flows return no credentials. Approved flows consume and return the
/// token, clearing the store's temporary token so normal repeated polling yields Consumed.
/// This does not guarantee retrieval of the same token after response loss and is separate
/// from browser-cookie authentication.
async fn post_device_login_poll(
State(api): State<ServerAuthApi>,
Json(request): Json<DeviceLoginPollRequest>,
@@ -1,4 +1,11 @@
//! Profile recipes are selected by the caller. Execution grants remain Host owned.
//! Backend Job Profile selection and explicit grant checks.
//!
//! Resolves the caller's registry Profile from the Workspace virtual config bundle and Prompt
//! projection, using public catalog recipes separately from browser launch filtering. Raw sources
//! and path selectors are rejected; instructions/features are not replaced with another default
//! recipe. Recipes requiring Workspace mutation, Memory, child/peer, Workdir, Flow, or MCP authority
//! absent from the Job are rejected. subjektiv also checks explicit consolidation grants and feature
//! requirements; Profile selection alone creates no domain authority.
use super::*;
impl WorkspaceApi {
@@ -1,4 +1,35 @@
//! Workspace identity-bound operation reception. Runtime/controller remain execution authority.
//! Worker operation admission based on Workspace registration.
//!
//! [`WorkspaceWorker`] fixes Runtime/Worker identity; it is not a lease guaranteeing a live
//! execution or authorization. Each operation rereads registration and revalidates the request's
//! Account or Worker control grant before delegating to Runtime. The controller determines actual
//! Idle/Busy state and input admission; catalog state alone cannot determine execution eligibility.
//!
//! # Caller and input boundaries
//!
//! The Server builds [`WorkerOperationContext`] from authentication results. Worker control locks
//! per grant and rechecks the same grant ID and permissions after waiting. Account requests reread
//! credentials, Account, and active Workspace, also checking browser session Origin. Test-only
//! Backend contexts do not exist in production.
//!
//! Worker control converts User input to UserIfIdle, never queuing Submit for a running Worker.
//! Notify requires separate permission. Normal input is denied to Backend Job Workers and Workers
//! with unsettled Ticket claims. Only Runtime Accepted Stop closes the current Workdir session
//! and synchronizes attachments. WorkerRemove is a separate contract: it verifies a target-bound
//! proof, then rechecks grants and retention in the removal service.
//!
//! # Connections and results
//!
//! Dedicated and multiplexed WS use the same [`WorkspaceWorkerMethodSender`]. Connections check
//! observe; method sends check send_input and browser context. Successful sends mean transport
//! channel enqueue, not controller acknowledgment or durable Submit/Notify receipts.
//! Actual results arrive through the event stream. Connections bind to one execution and do not
//! implicitly reconnect or Restore into the next execution with the same Worker ID.
//!
//! Unary input lacks the WS Submit replay-key contract; unknown delivery outcomes remain diagnostic.
//! Restore observation tokens, controller command IDs, Submit/Notify request IDs, and cleanup plan
//! digests have separate verifying owners, not a shared success criterion or replay contract.
//! Internal SubWorkers are parent Worker sessions, outside this Workspace registry handle.
use super::*;
/// Caller authority supplied by authenticated Server adapters, never public JSON/identity hints.
@@ -1,11 +1,19 @@
//! Workspace lifecycle admission, not operation serialization.
//! Admission gate coordinating Workspace deletion with HTTP handler lifetimes.
//!
//! Resource owners retain their own locks/transactions. Deletion first stops
//! ordinary admission, then drains admitted requests. Synchronous Runtime
//! callbacks remain admissible while a parent request is still running; once
//! the last ordinary request leaves, callback admission also closes. This
//! avoids both callback/deletion cycles and an unbounded stream of new work
//! starving deletion. All leases, including the deletion fence, are RAII.
//! Normal requests acquire leases immediately; independent handlers can run concurrently.
//! Resource owners handle Worker, Workdir, and SQLite exclusion; this gate does not serialize them.
//! Business-operation lock waits do not precede proof verification, avoiding expiry of short-lived
//! proofs while waiting for other requests.
//!
//! Deletion closes normal admission before draining existing handlers. Only Runtime callbacks
//! needed by active parent requests may acquire tracked leases; callback admission also closes
//! when the last normal lease leaves. This prevents deletion blocking callbacks awaited by parents
//! and callbacks indefinitely extending the drain. Callbacks still require authentication and
//! authorization.
//!
//! Drop releases leases and temporary deletion fences. Cancelling a deletion wait reopens normal
//! admission, but durable Workspace state blocks admission after deletion reservation succeeds.
//! Leases cover HTTP responses, not the full lifetime of upgraded WS or background work.
use std::sync::{Arc, Mutex};
use tokio::sync::{Mutex as AsyncMutex, Notify, OwnedMutexGuard};
@@ -1,5 +1,9 @@
//! Authorized Workspace document API. Storage, CAS and receipts stay in workspace-drive.
//! HTTP upload consumes frames with a hard bound; DB publication occurs only after validation.
//!
//! HTTP errors and stream failures use fixed public representations, without Host storage paths
//! or raw diagnostics. Unknown mutation outcomes are OutcomeUnknown; response failure does not
//! prove the mutation was uncommitted.
use super::*;
use futures::StreamExt;
use server_api::*;
@@ -1,5 +1,9 @@
//! Drive authority is rechecked inside the metadata transaction against the
//! attached Server DB. A bound handle is not an authorization cache or lease.
//! Authorizes Drive operations against current grants in the connected Server DB.
//!
//! Checks before upload body reception only admit the request; handles retain no authority.
//! Each operation's metadata transaction rechecks Worker liveness, unrevoked grants, and write
//! permission. Human requests also check current User/Account and active Workspace. Incomplete
//! or contradictory Worker/Runtime sources do not fall back to Account authority.
use super::*;
use rusqlite::params;
use server_api::{
@@ -3,6 +3,12 @@
//! Files support read/edit/write and non-entrypoint deletion; directories support
//! create, with atomic change sets (including non-entrypoint renames) on the root.
//! The canonical main.dcdl entrypoint cannot be deleted or renamed.
//!
//! Worker operations reread unrevoked grants and current attachment connection IDs after acquiring
//! the session lock. Observation validators bind to grant, effective access, connection, config
//! content, and schema, rejecting stale observations or writes after grant replacement.
//! Write permission is the intersection of grant and attachment permissions; authorization at
//! handle acquisition is not ongoing authority.
use super::*;
use server_api::{
WorkspaceConfigAccess as Access, WorkspaceConfigApiError as Failure,
+28
View File
@@ -1,3 +1,31 @@
//! SQLite persistence and schema consistency for Workspace resources.
//!
//! # Startup and migrations
//!
//! Normal open, migration preflight, and explicit application share connection preparation.
//! Preflight copies a read-only source into memory and exercises the full migration without
//! changing the source DB. Existing DBs apply retained migrations in order; new DBs use the
//! latest canonical schema. A partially committed migration sequence is a valid history prefix
//! from which the next attempt resumes.
//!
//! Schema history must match the retained baseline's version/name sequence. Unknown, modified,
//! misordered, or unsupported histories are rejected. Workspace table rebuilds across domains
//! align with Ticket/Merge Request validation and ordering, then validate resource references
//! and foreign keys. Recovery requirements, such as unresolved legacy deletion receipts, block
//! migration before it starts. Updating only the new schema would diverge from existing DBs;
//! both creation paths must maintain the same contract.
//!
//! # Resource state and operation records
//!
//! Workspace bootstrap commits resources and creation receipts in one transaction. Jobs and
//! Workdir deletion span Runtime/providers, so immutable intent and evidence of external results
//! are stored separately. The Worker registry retains persistent identity, assignment, retention,
//! and observation projections; it does not replace controller input admission or Runtime lifecycle.
//!
//! The internal Restore journal records client intent with a request ID and observation token
//! fixed before sending. Unknown outcomes and restarts reuse that pair, settling on a confirmed
//! result. This is not a second lifecycle state machine duplicating Runtime operations or receipts.
use std::collections::{BTreeSet, HashMap, HashSet};
use std::path::Path;
use std::sync::{Arc, Mutex};
@@ -1,7 +1,20 @@
//! Post-save Ticket item checks executed through the Backend-owned Job runner.
//! Asynchronous advisory checks of saved Ticket content using Backend Jobs.
//!
//! The immutable input contains only the persisted Ticket item and the edit that
//! produced it. Conversation history is deliberately outside this boundary.
//! Authenticated Worker Create/EditItem paths freeze check input and reserve a Job after saving.
//! Failed preparation, execution, or delivery does not roll back the save or change Ticket state,
//! Queue, or assignments. Direct browser edits have no notification Worker and start no check.
//!
//! Input is limited to saved title/body, content digest, and the prior body/replacement context
//! needed for that edit, excluding conversation, user agreements, and external facts. Content
//! digests identify advisory freshness, not Job intent. Identical content with different edit
//! context or sources creates different Jobs; oversized input is not truncated and marked checked.
//!
//! Results are checked for unknown fields, duplicates, count/string limits, and quotes that are
//! exact substrings of the checked title/body. Invalid results end as invalid_result.
//! Delivery rereads the Ticket and notifies the original Worker only of findings matching the
//! saved digest. No findings and stale results end delivery with distinct suppression reasons,
//! without redelivery on recovery. Advice is neither an approval gate nor implementation guidance;
//! no findings do not prove the entire specification correct.
use std::collections::BTreeSet;
@@ -1,3 +1,12 @@
//! Persists immutable Workdir creation intent and Repository credential candidates.
//!
//! Creation fingerprints identify Repository source, selector, requested Runtime, and display
//! name. Replay retains saved selectors and resolved resources, not current defaults. Store
//! reservations reject differences under the same operation ID; SSH candidates fix identity at
//! selection. Retained generated Workdir IDs and candidates support provider retries, not proof
//! of creation. Creation retries do not start on resources with pending removal; transitions
//! from failed to pending also check the current deletion fence within a transaction.
use rusqlite::{OptionalExtension, TransactionBehavior, params};
use sha2::{Digest, Sha256};
+20 -6
View File
@@ -1,10 +1,24 @@
//! Durable, retryable Backend authority for persistent Workdir removal.
//! Persists durable deletion intent and attempts for Repository-backed Workdirs.
//!
//! Runtime cleanup is an external side effect, so callers reserve one immutable
//! operation before invoking the provider. The final registry deletion and
//! operation completion are committed atomically. If a process stops after the
//! provider side effect but before that transaction, recovery re-observes the
//! provider and converges through the same operation.
//! Deletion intent fixes Workspace, Workdir, owning Runtime, Repository/materialization, actor,
//! and reason. Endpoints, host paths, and provider handles do not grant caller deletion authority.
//! External Workdirs follow grant revocation, not this operation.
//!
//! Only one pending operation per Workdir is allowed; attempts are claimed transactionally.
//! Process IDs and startup markers are retained. Recovery reclaims the exact owner/attempt by
//! compare-and-set only after confirming the previous owner is gone; live or unobservable owners
//! are not displaced. In-process locks alone are insufficient.
//!
//! Server execution revalidates stored materialization and current attachments, reservations,
//! assignments, retention, and creation operations, then observes occupancy and cleanliness via
//! Runtime. Dirty resources remain; unknown observations or provider failures retain the registry
//! and record attention/retryability. Only confirmed deletion or exact working_directory_not_found
//! is deletion evidence; registry removal and completed/removed commit in the same transaction.
//!
//! Normal deletion, Workspace deletion, cleanup, and startup recovery use the same reserved Server
//! operation execution. Failed DB commits after provider deletion are reobserved through that
//! operation. Recovery relies on provider identity and results, not an exactly-once guarantee
//! across all interruption points.
use chrono::Utc;
use rusqlite::{Connection, OptionalExtension, TransactionBehavior, params};
@@ -1,3 +1,15 @@
//! Backend boundary verifying Runtime-origin requests and WorkerRemove source proofs.
//!
//! Runtime signatures are verified against current Workspace bindings and the Backend audience.
//! Hint headers such as Worker IDs do not authenticate. General request proofs and target-bound
//! WorkerRemove proofs are separate contracts; removal services recheck control grants/retention
//! after verification. Embedded removal also consumes Runtime-generated in-process proofs,
//! without falling back to hints.
//!
//! Signature/request/time checks alone do not admit proofs: JTI consumption and current Worker
//! registration, reservations, and singleton ownership are checked too. Diagnostic verification
//! stages show progress, not an authenticated principal.
use std::sync::{Arc, OnceLock};
use std::time::{SystemTime, UNIX_EPOCH};
@@ -1,3 +1,19 @@
//! Runtime request proof verification and secret-free rejection diagnostics.
//!
//! Unverified issuers only select public keys from current Workspace bindings. After matching
//! signature, Backend audience, Workspace, permission, method, path/query, body digest, and time,
//! verification consumes the JTI transactionally and checks Worker registration or creation
//! reservations and singleton ownership. One sampled clock serves time checks and JTI records;
//! the lower-level verifier owns tolerance and ordering. Diagnostics do not recompute rejection
//! with another clock.
//!
//! Rejection reasons expose only safe categories and verification stages. Claim-derived identities
//! use domain-separated hashes, omitted on decode failure. request_verified may still precede
//! replay/registration/ownership checks; it is not an authenticated principal. Diagnostics do not
//! infer key-mismatch causes or absence/revocation distinctions the store does not make.
//! Proofs, raw claims, keys, bodies, and store error text are not retained. Identity hashes are
//! not encryption and do not make guessable IDs secret.
use worker_runtime::auth::{
RuntimeAuthError, RuntimeRequestClaim, RuntimeRequestSourceClaims,
RuntimeRequestSourceExpectation, decode_runtime_request_source_claims,
@@ -1,3 +1,20 @@
//! Workspace creation and replay without requiring a Repository.
//!
//! Workspace identity is independent of Git Repositories and Workdirs. Omitting the initial
//! Repository means no asset, not Git initialization or an inferred substitute. Supplied objects
//! undergo normal validation; invalid input is not omission. The owner is the Account supplied
//! by the authentication adapter.
//!
//! Normalized requests and owners produce fingerprints. After signing material reservation and
//! preparation, the store bootstrap transaction commits Workspace, optional Repository, initial
//! settings, signing identity, and creation receipt. Different input under the same operation key
//! conflicts. Replaying material preparation retains the reserved Workspace/key identities.
//!
//! Replay returns current Workspace/settings, not creation snapshots. With an initial Repository,
//! it returns the asset currently registered under the original key, or None after deletion/rename,
//! without reregistration or initialization. Requests originally omitting Repository replay as
//! None even if assets were added later.
use std::sync::Arc;
use chrono::{SecondsFormat, Utc};
@@ -1,4 +1,9 @@
//! Trusted Host placement and lifecycle for Workspace Drive (no HTTP/DTO surface).
//!
//! Workspace deletion reservations reject even existing handles through transaction serialization
//! with the Server DB. Deletion starts with a durable Drive fence and settles purge tombstones and
//! blob/metadata deletion before deleting FeatureStorage. Blob deletion failures retain
//! FeatureStorage; partial failure is not completion.
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicBool, Ordering};
@@ -1,3 +1,14 @@
//! Consistency of per-Workspace signing identities and private material.
//!
//! The store retains public identities and material references; a separate store manages private
//! material. Workspace creation first reserves immutable Workspace/key/material references and
//! prepares the same material on replay. Bootstrap activates it after checking public key/material
//! agreement. Successful material preparation alone does not commit Workspace creation.
//!
//! Capability issuance selects the current active identity, checks the claims' Workspace, key ID,
//! and fingerprint against it, then signs. Missing/corrupt material does not fall back to a shared
//! Server key. Debug redacts private material; Drop zeroizes private key strings.
use std::fmt;
use std::fs::{self, OpenOptions};
use std::io::Write;