# kcode-kennedy-roots 0.1.0
`kcode-kennedy-roots` owns the mechanical bootstrap and validation of Kennedy's
two application system roots and reconciliation of Telegram identity-directory
root assignments. It applies Kennedy's fixed root metadata through typed Kweb
Manager and identity-directory APIs while leaving persistence paths, writer
authorization, the primary web handle, and scheduling with the application.
## Complete public API
```rust
#[derive(Clone, Copy, Debug)]
pub struct SystemRoots {
pub user: kcode_kweb_db::NodeId,
pub kennedy: kcode_kweb_db::NodeId,
}
pub fn open(
kweb_root: &std::path::Path,
config: kcode_kweb_db::Config,
identity_database: &std::path::Path,
) -> anyhow::Result<(kcode_kweb_manager::KwebManager, SystemRoots)>;
#[derive(Clone)]
pub struct DirectoryRoots { /* private shared handles and policy */ }
impl DirectoryRoots {
pub fn new(
kmap: kcode_kweb_manager::KwebManager,
directory: std::sync::Arc<kcode_telegram_identity::Directory>,
web_user_handle: impl Into<String>,
system_user_root: kcode_kweb_db::NodeId,
writer: std::sync::Arc<tokio::sync::Mutex<()>>,
) -> Self;
pub async fn reconcile_pending(&self) -> anyhow::Result<()>;
pub async fn ensure_user(
&self,
telegram_user_id: i64,
) -> anyhow::Result<kcode_telegram_identity::User>;
pub async fn ensure_group(
&self,
group_id: &str,
) -> anyhow::Result<kcode_telegram_identity::Group>;
}
```
## System-root bootstrap
`open` opens the identity SQLite database and Kweb database, ensures the
`kmap_system_roots` directory exists, and accepts only the complete state in
which both roots already exist or neither does. On first use it creates both
nodes in one signed Kweb transaction, commits their canonical identifiers to
the identity database in one SQL transaction, validates that both nodes are
readable, and transfers the sole live database into `KwebManager`.
An identity database containing only one root fails closed. Existing root IDs
must be valid canonical Kweb identifiers and must resolve through Kweb.
## Directory reconciliation
`DirectoryRoots` is cheaply cloneable. Every root-creating operation holds the
application-supplied writer mutex, reloads the identity after acquiring it, and
therefore shares Kennedy's one global Kweb writer lane without retaining stale
directory state.
`reconcile_pending` completes every directory user and group waiting for a
root. The configured primary web handle is assigned the canonical system user
root; other users receive a new User Root and groups receive a new Group Root.
It processes complete owner operations rather than exposing create/assign
steps to the caller.
`ensure_user` and `ensure_group` return an already-ready identity unchanged or
create and assign its root atomically with respect to the supplied writer lane.
Unknown identities and directory conflicts remain actionable errors from the
identity owner.
## Ownership and persistence
The library owns only application root mechanics and the `kmap_system_roots`
table. Kweb Manager remains the sole live graph/database owner after `open`;
Telegram Identity remains the directory owner. The library does not own paths,
authorization policy, Telegram transport, sessions, prompts, retries, or a
second writer scheduler.