# Client core ownership and runtime contract

`GridClient` construction is deliberately inert. `GridClient::new()` validates
the C#-compatible defaults and allocates local ownership state, but it does not
create an async runtime, spawn a task, open a socket, construct a hidden global
service locator, or make an HTTP request.

Applications that need custom settings, a deterministic clock, or native
manager implementations use the explicit builder:

```rust
use libremetaverse::{GridClient, Settings};
use libremetaverse_types::compat::TimeProvider;
use std::time::{Duration, SystemTime};

let mut settings = Settings::default();
settings.timing().login_timeout = 30_000;

let fixed = SystemTime::UNIX_EPOCH + Duration::from_secs(1_000);
let client = GridClient::builder()
    .with_settings(settings)
    .with_time_provider(TimeProvider::from_fn(move || fixed))
    .build()?;
# Ok::<(), libremetaverse::ClientCoreError>(())
```

Native services implement `ClientService` and are passed to
`GridClientBuilder::with_service` after the application has constructed them.
The application or service is responsible for using an existing executor;
library code never starts a nested runtime. Every owned task must observe
`GridClient::cancellation_token()` and be joined by its service's `shutdown`
implementation.

Shutdown is idempotent. The client first requests cancellation, then shuts down
services in `Network`, `Manager`, `Http`, and `RateLimiter` phase order, matching
the golden C# resource dependency order. Dropping a client performs the same
shutdown path. Services must release their tasks and resources before returning.
User callbacks must never run while a service holds an internal lock.

`Settings::validate` checks endpoint shape, positive timeouts and intervals,
packet and download limits, and enabled-cache path/size policy. Builder errors
identify the public field without copying its value. `Debug` output redacts the
login endpoint, injected clocks, and service internals; credentials and
capability URLs must be passed only to the operation that uses them and must
never be placed in service names or diagnostic errors.
