Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
d4abf06
build(crypto): scaffold SquidStd.Crypto module over PgpCore
tgiachi Jun 28, 2026
fd3abe8
feat(crypto): add PGP key model, options, and result DTOs
tgiachi Jun 28, 2026
22bc121
feat(crypto): add PGP service, keyring, and key store contracts
tgiachi Jun 28, 2026
d0ff4b3
feat(crypto): parse PGP key metadata from armored material
tgiachi Jun 28, 2026
2799b41
feat(crypto): add in-memory PGP keyring indexed by identity, key id, …
tgiachi Jun 28, 2026
2b4c754
feat(crypto): PGP key generation and encrypt/decrypt over the keyring
tgiachi Jun 28, 2026
164e761
feat(crypto): PGP sign/verify and encrypt-and-sign/decrypt-and-verify
tgiachi Jun 28, 2026
33a5e94
feat(crypto): add file-backed PGP key store (armored .asc files)
tgiachi Jun 28, 2026
a560a69
feat(crypto): add AES-GCM encrypted PGP key store via ISecretProtector
tgiachi Jun 28, 2026
ee197da
feat(crypto): add RegisterPgp DI extension
tgiachi Jun 28, 2026
62fab40
docs(crypto): add SquidStd.Crypto README and format module
tgiachi Jun 28, 2026
67dd8e6
Merge branch 'feature/crypto-pgp' into develop
tgiachi Jun 28, 2026
00ace04
build(vfs): scaffold SquidStd.Vfs.Abstractions and SquidStd.Vfs modules
tgiachi Jun 28, 2026
0efecc5
feat(vfs): add virtual filesystem abstraction and lockable contract
tgiachi Jun 28, 2026
e4f4e9e
feat(vfs): add path normalization and physical filesystem provider
tgiachi Jun 28, 2026
02ff3ba
feat(vfs): add in-memory filesystem provider
tgiachi Jun 28, 2026
fe8fe56
feat(vfs): add zip-backed filesystem provider
tgiachi Jun 28, 2026
4b583c4
feat(vfs): add VfsDirectories and RegisterVfs DI extension
tgiachi Jun 28, 2026
057b93f
feat(crypto): add vault options and Argon2id/HKDF key derivation
tgiachi Jun 28, 2026
68afcc7
feat(crypto): add chunked AES-GCM entry cipher
tgiachi Jun 28, 2026
94f46e2
feat(crypto): add vault header and encrypted-index models
tgiachi Jun 28, 2026
18b70a6
feat(crypto): add crypto vault unlock/lock and index lifecycle
tgiachi Jun 28, 2026
e40349d
feat(crypto): implement encrypted per-entry read/write/delete/list
tgiachi Jun 28, 2026
750cd35
feat(crypto): add RegisterCryptoVault DI extension
tgiachi Jun 28, 2026
eab6e82
docs(vfs): add SquidStd.Vfs README and crypto vault docs; format module
tgiachi Jun 28, 2026
804cfa3
Merge branch 'feature/vfs-crypto-vault' into develop
tgiachi Jun 28, 2026
8a4fbde
feat(secrets): add ListNamesAsync to ISecretStore and FileSecretStore
tgiachi Jun 28, 2026
a225409
build(secrets): scaffold SquidStd.Secrets.Aws module
tgiachi Jun 28, 2026
8478e48
feat(secrets): add KMS envelope-encryption secret protector
tgiachi Jun 28, 2026
0a2cffd
feat(secrets): add AWS Secrets Manager store
tgiachi Jun 28, 2026
ed5a6d7
feat(secrets): add RegisterKmsSecretProtector and RegisterAwsSecretsM…
tgiachi Jun 28, 2026
0670eb3
docs(secrets): add SquidStd.Secrets.Aws README and format module
tgiachi Jun 28, 2026
370c539
Merge branch 'feature/secrets-aws-adapters' into develop
tgiachi Jun 28, 2026
1479482
docs: group package list by domain in README
tgiachi Jun 28, 2026
c00e439
docs: expand root README with TOC, templates, fuller example and ackn…
tgiachi Jun 28, 2026
ec6a445
docs: rewrite landing page with full surface and Diátaxis entry points
tgiachi Jun 28, 2026
d895bf8
docs: refresh getting-started with current bootstrap API
tgiachi Jun 28, 2026
4dbca35
docs: add reference articles for Actors, Crypto, Vfs, Secrets.Aws and…
tgiachi Jun 28, 2026
a7ba8d5
docs: normalise core & hosting package READMEs
tgiachi Jun 28, 2026
a961341
docs: normalise networking & actors package READMEs
tgiachi Jun 28, 2026
ea2e5ab
docs: normalise messaging package READMEs
tgiachi Jun 28, 2026
39bce51
docs: normalise persistence & database package READMEs
tgiachi Jun 28, 2026
e3c4bb5
docs: normalise caching package READMEs
tgiachi Jun 28, 2026
523e4ea
docs: normalise storage & vfs package READMEs
tgiachi Jun 28, 2026
91f7b0f
docs: normalise security package READMEs
tgiachi Jun 28, 2026
c721792
docs: normalise search & mail package READMEs
tgiachi Jun 28, 2026
01036af
docs: normalise workers package READMEs
tgiachi Jun 28, 2026
02d61f0
docs: normalise scripting, templating & telemetry package READMEs
tgiachi Jun 28, 2026
f1befec
docs: normalise core & hosting package READMEs
tgiachi Jun 28, 2026
fefba85
docs: normalise networking & actors package READMEs
tgiachi Jun 28, 2026
3e458ce
docs: normalise messaging package READMEs
tgiachi Jun 28, 2026
bbf6d1b
docs: normalise persistence & database package READMEs
tgiachi Jun 28, 2026
943507b
docs: normalise caching package READMEs
tgiachi Jun 28, 2026
eea8bf9
docs: harmonise package README headers to the bare-h1 template
tgiachi Jun 28, 2026
431dac2
docs: remove stray tool-output tags from Messaging.Sqs and Generators…
tgiachi Jun 28, 2026
2b78a40
docs: add Concepts explanation pages with Mermaid diagrams
tgiachi Jun 28, 2026
d01cf9a
docs: add Concepts section to articles TOC
tgiachi Jun 28, 2026
645d270
docs: add how-to and provider decision guides
tgiachi Jun 28, 2026
d7e255f
docs: add Guides section to articles TOC
tgiachi Jun 28, 2026
a8e7c69
build: add Crypto sample project
tgiachi Jun 28, 2026
feba497
build: add Vfs sample project
tgiachi Jun 28, 2026
73d4783
build: add Secrets sample project
tgiachi Jun 28, 2026
f2fa0aa
build: add Actors sample project
tgiachi Jun 28, 2026
a222049
docs(samples): show real keyring persistence in Crypto sample
tgiachi Jun 28, 2026
2c95b77
docs(samples): make Vfs vault step an honest working round-trip
tgiachi Jun 28, 2026
dc5b958
build: add step regions to Commands sample
tgiachi Jun 28, 2026
6fee64f
docs: add crypto, vfs, secrets, actors, persistence and command-dispa…
tgiachi Jun 28, 2026
f767a42
docs: add new tutorials to TOC
tgiachi Jun 28, 2026
e357df7
docs: link tutorials and concepts from the new-module READMEs
tgiachi Jun 28, 2026
49c9d0e
Merge branch 'feature/docs-overhaul' into develop
tgiachi Jun 28, 2026
b0c7c06
fix(vfs): make on-disk crypto vault persist and stop ListAsync crashing
tgiachi Jun 28, 2026
d3d19f6
Merge branch 'fix/crypto-vault-disk-persistence' into develop
tgiachi Jun 28, 2026
11aaf7a
fix(vfs,crypto,actors): harden vault decoding, isolate reads, and mak…
tgiachi Jun 29, 2026
143b486
fix(persistence,network,rabbitmq): per-type replay, harden journal/UD…
tgiachi Jun 29, 2026
3f79420
Merge branch 'fix/audit-batch' into develop
tgiachi Jun 29, 2026
95969b8
fix(actors): drain queued messages on dispose instead of dropping them
tgiachi Jun 29, 2026
e2c7121
Merge branch 'fix/actor-graceful-drain' into develop
tgiachi Jun 29, 2026
a47a2b3
fix(persistence): write the journal before applying an entity mutatio…
tgiachi Jun 29, 2026
c35d91b
fix(persistence): serialize SaveSnapshotAsync so concurrent runs cann…
tgiachi Jun 29, 2026
8adbf32
fix(persistence): checksum the whole snapshot envelope, not just the …
tgiachi Jun 29, 2026
3179da1
feat(persistence): add DurabilityMode config option (default Buffered)
tgiachi Jun 29, 2026
37f3887
feat(persistence): optional fsync durability for journal and snapshot…
tgiachi Jun 29, 2026
21d331c
fix(persistence): disambiguate snapshot files by TypeId and migrate l…
tgiachi Jun 29, 2026
d10ff9b
fix(network): bound per-connection TCP frame size to prevent unbounde…
tgiachi Jun 29, 2026
3c3cd09
Merge branch 'fix/audit-remediation-batch2' into develop
tgiachi Jun 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
206 changes: 181 additions & 25 deletions README.md

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions SquidStd.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
<Project Path="src/SquidStd.Mail.Abstractions/SquidStd.Mail.Abstractions.csproj" />
<Project Path="src/SquidStd.Mail.MailKit/SquidStd.Mail.MailKit.csproj" />
<Project Path="src/SquidStd.Mail.Queue/SquidStd.Mail.Queue.csproj" />
<Project Path="src/SquidStd.Crypto/SquidStd.Crypto.csproj" />
<Project Path="src/SquidStd.Vfs.Abstractions/SquidStd.Vfs.Abstractions.csproj" />
<Project Path="src/SquidStd.Vfs/SquidStd.Vfs.csproj" />
<Project Path="src/SquidStd.Secrets.Aws/SquidStd.Secrets.Aws.csproj" />
</Folder>
<Folder Name="/samples/">
<Project Path="samples/SquidStd.Samples.WorkerSystem/SquidStd.Samples.WorkerSystem.csproj" />
Expand All @@ -55,6 +59,10 @@
<Project Path="samples/SquidStd.Samples.Caching/SquidStd.Samples.Caching.csproj" />
<Project Path="samples/SquidStd.Samples.EventsJobsScheduling/SquidStd.Samples.EventsJobsScheduling.csproj" />
<Project Path="samples/SquidStd.Samples.GettingStarted/SquidStd.Samples.GettingStarted.csproj" />
<Project Path="samples/SquidStd.Samples.Crypto/SquidStd.Samples.Crypto.csproj" />
<Project Path="samples/SquidStd.Samples.Vfs/SquidStd.Samples.Vfs.csproj" />
<Project Path="samples/SquidStd.Samples.Secrets/SquidStd.Samples.Secrets.csproj" />
<Project Path="samples/SquidStd.Samples.Actors/SquidStd.Samples.Actors.csproj" />
</Folder>
<Folder Name="/tests/">
<Project Path="tests/SquidStd.Tests/SquidStd.Tests.csproj" />
Expand Down
1 change: 1 addition & 0 deletions docs/articles/actors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[!include[](../../src/SquidStd.Actors/README.md)]
21 changes: 21 additions & 0 deletions docs/articles/concepts/abstractions-first.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Abstractions first

SquidStd is built abstractions-first: code depends on contracts, and concrete backends are chosen at composition time. This is what makes a SquidStd application easy to test and easy to retarget.

## Contract package plus provider packages

Each capability is a contract package paired with one or more provider packages. The contract package — `*.Abstractions` — defines the interfaces and DTOs. Provider packages implement them. Your application references the abstraction and depends on the provider only in the host project. See the [architecture](architecture.md) overview for how this shapes the package graph.

## In-memory for tests, external for prod

Most capabilities ship an in-memory provider for tests and an external-backend provider for production:

- **Messaging** — in-memory, or `SquidStd.Messaging.RabbitMq` / `SquidStd.Messaging.Sqs`.
- **Caching** — in-memory, or `SquidStd.Caching.Redis`.
- **Storage** — file-backed, or `SquidStd.Storage.S3` (S3 and MinIO).

Tests run fast and deterministically against the in-memory provider; production swaps in the external backend.

## Swapping providers without touching call sites

Because call sites depend only on the contract, switching backends is a registration change in the host — `container.AddInMemoryMessaging()` versus `container.AddRabbitMqMessaging(...)` — with no edits to the code that publishes or consumes messages. See [dependency injection](dependency-injection.md) for the registration pattern that makes the swap a one-line change.
34 changes: 34 additions & 0 deletions docs/articles/concepts/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Architecture

SquidStd is a modular .NET toolkit. Rather than a single monolithic library, it ships one package per capability, so an application depends only on the pieces it actually uses.

## Modular by design

Every capability is split in two: an `*.Abstractions` package that holds the contracts (interfaces and DTOs) and one or more provider packages that implement them. For example `SquidStd.Messaging.Abstractions` defines the messaging contracts, while `SquidStd.Messaging`, `SquidStd.Messaging.RabbitMq`, and `SquidStd.Messaging.Sqs` provide implementations. This keeps call sites coupled to contracts, not to a concrete backend. See [abstractions first](abstractions-first.md) for why this matters.

## Layers

The dependency flow runs in one direction:

- **Core** (`SquidStd.Core`) — primitives, options, and the building blocks everything else sits on.
- **Abstractions** — per-capability contract packages.
- **Providers** — concrete implementations of those contracts.
- **Host** — `SquidStdBootstrap` composes services and runs them.

Higher layers depend on lower ones, never the reverse.

## Package graph

```mermaid
graph TD
Core[SquidStd.Core] --> Services[SquidStd.Services.Core]
Abstr[*.Abstractions contracts] --> Providers[Provider packages]
Services --> Host[SquidStdBootstrap host]
Providers --> Host
Host --> App[Your application]
```

## Next

- [Bootstrap lifecycle](bootstrap-lifecycle.md) — how the host starts and stops services.
- [Abstractions first](abstractions-first.md) — the contract-plus-provider pattern in depth.
51 changes: 51 additions & 0 deletions docs/articles/concepts/bootstrap-lifecycle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Bootstrap lifecycle

`SquidStdBootstrap` is the entry point that wires up dependency injection and drives the lifecycle of every registered service. The flow is always the same: create, configure, start, stop.

## Create

Begin by creating the bootstrap from `SquidStdOptions`:

```csharp
var bootstrap = SquidStdBootstrap.Create(new SquidStdOptions
{
ConfigName = "squidstd",
RootDirectory = AppContext.BaseDirectory
});
```

`ConfigName` selects the configuration file and `RootDirectory` anchors relative paths.

## ConfigureServices

Register your services into the DryIoc container:

```csharp
bootstrap.ConfigureServices(container =>
{
container.AddSomething();
});
```

See [dependency injection](dependency-injection.md) for the container and the `AddXxx` / `RegisterXxx` pattern.

## Start and stop over ISquidStdService

Services implementing `ISquidStdService` participate in the lifecycle. On `StartAsync` they are started in registration order; on `StopAsync` they are stopped in reverse order, so dependencies remain available while their dependents shut down.

```mermaid
sequenceDiagram
participant App
participant Bootstrap as SquidStdBootstrap
participant Svc as ISquidStdService(s)
App->>Bootstrap: Create(options)
App->>Bootstrap: ConfigureServices(container)
App->>Bootstrap: StartAsync()
Bootstrap->>Svc: StartAsync() (in order)
App->>Bootstrap: StopAsync()
Bootstrap->>Svc: StopAsync() (reverse order)
```

## RunAsync for long-running hosts

For long-running hosts, call `RunAsync`. It starts every service and then blocks until cancellation, stopping services cleanly on shutdown. Resolve dependencies anywhere with `bootstrap.Resolve<T>()`. See the [architecture](architecture.md) overview for how the host fits the layers.
32 changes: 32 additions & 0 deletions docs/articles/concepts/dependency-injection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Dependency injection

SquidStd resolves every service through dependency injection. Understanding the container and its registration pattern is the key to wiring an application together.

## DryIoc container

The DI container is [DryIoc](https://github.com/dadhi/DryIoc), exposed as `IContainer`. It is fast, supports rich lifetimes, and validates required services at resolution time. Because the container owns validation, constructor dependencies that arrive from DI do not need manual null guards.

## The AddXxx / RegisterXxx extension pattern

Modules register themselves through C# 14 `extension(IContainer)` members named `AddXxx(...)` or `RegisterXxx(...)`. Each capability ships its own registration entry point, so wiring a module is a single call:

```csharp
container.AddInMemoryMessaging();
container.RegisterCoreServices();
```

This keeps registration discoverable and colocated with the package that owns it.

## Resolving through the bootstrap

Once configured, resolve services through the bootstrap:

```csharp
var bus = bootstrap.Resolve<IEventBus>();
```

In most code you let constructor injection do the work and never call `Resolve` directly. See [bootstrap lifecycle](bootstrap-lifecycle.md) for where `ConfigureServices` runs.

## Singletons and lifecycle

Most infrastructure services are registered as singletons and live for the life of the host. Services implementing `ISquidStdService` are additionally started and stopped by the bootstrap, so a singleton can hold long-lived resources that are released on shutdown.
27 changes: 27 additions & 0 deletions docs/articles/concepts/messaging-models.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Messaging models

SquidStd offers three in-process messaging models. Each fits a different shape of communication, and they can be mixed freely within one application.

## Event Bus

The Event Bus (`IEventBus`) is a stateless broadcast. Publishers call `PublishAsync` and any number of subscribers registered with `Subscribe` receive the event. Senders do not know who listens, and there is no return value. Use it for fan-out notifications where many parts of the system react to something that happened.

## Command Dispatcher

The Command Dispatcher is a stateless request routed to a single handler that returns a result. Unlike the Event Bus there is exactly one handler per command, and the caller awaits its result. Use it for request/response work — validating input, performing an operation, returning an outcome — where ownership of the action is unambiguous.

## Actors

Actors (`Actor<TMessage>`) provide an ordered, stateful, per-entity mailbox. Each actor processes its messages one at a time in order, so state inside an actor needs no locks. Send fire-and-forget messages with `TellAsync` or request a reply with `AskAsync`. Use actors when you need serialized access to per-entity state, such as a single account, device, or session.

## Choosing

```mermaid
flowchart TD
Q{Need ordered, per-entity state?} -->|yes| A[Actors]
Q -->|no| R{Request → single handler with a result?}
R -->|yes| C[Command Dispatcher]
R -->|no| E[Event Bus broadcast]
```

All three are contract-first; see [abstractions first](abstractions-first.md) for swapping in external transports.
1 change: 1 addition & 0 deletions docs/articles/crypto.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[!include[](../../src/SquidStd.Crypto/README.md)]
19 changes: 12 additions & 7 deletions docs/articles/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,19 @@ dotnet add package SquidStd.Services.Core
```

```csharp
using DryIoc;
using SquidStd.Services.Core.Extensions;
using SquidStd.Core.Data.Bootstrap;
using SquidStd.Services.Core.Services.Bootstrap;

var container = new Container();
// Core services wired automatically: config manager, event bus, command dispatcher,
// job system, timer/cron scheduler, metrics, health checks, storage and secrets.
var bootstrap = SquidStdBootstrap.Create(
new SquidStdOptions { ConfigName = "squidstd", RootDirectory = AppContext.BaseDirectory });

// config manager + event bus + jobs + timer wheel + dispatcher + metrics + storage + secrets
container.RegisterCoreServices("squidstd", Directory.GetCurrentDirectory());
await bootstrap.StartAsync();
// … resolve services, opt into modules with bootstrap.ConfigureServices(…) …
await bootstrap.StopAsync();
```

From here, add focused packages as needed — see the per-package guides in the sidebar and the
[API reference](../api/index.md).
Opt into modules with `ConfigureServices`, e.g. `container.AddInMemoryCache()`. See the
[Concepts](concepts/bootstrap-lifecycle.md) for the full lifecycle and
[Packages](getting-started.md) for per-module reference.
19 changes: 19 additions & 0 deletions docs/articles/guides/choosing-caching.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Choosing a cache

The caching abstraction (`ICacheService`) has two backends. Both expose the same
API, so you can develop against in-memory and promote to Redis without code changes.

| Backend | Package · entrypoint | Use case | Scope | Survives restart | Ops cost |
|---|---|---|---|---|---|
| In-memory | `SquidStd.Caching` · `AddInMemoryCache` | Tests, single instance | Per-process | No | None |
| Redis | `SquidStd.Caching.Redis` · `AddRedisCache` | Multiple instances, shared cache | Distributed | Yes (with persistence) | Run/host Redis |

```csharp
bootstrap.ConfigureServices(container => container.AddRedisCache("localhost:6379"));
```

## Recommendation

Use `AddInMemoryCache` for tests and single-instance deployments; switch to
`AddRedisCache` as soon as you run more than one instance or need the cache to
outlive the process.
19 changes: 19 additions & 0 deletions docs/articles/guides/choosing-messaging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Choosing a messaging backend

SquidStd exposes one messaging abstraction with three interchangeable backends.
Pick by where you run and what delivery guarantees you need.

| Backend | Package · entrypoint | Use case | Ordering | Durability | Ops cost |
|---|---|---|---|---|---|
| In-memory | `SquidStd.Messaging` · `AddInMemoryMessaging` | Tests, single-process apps | Per-process | None (lost on restart) | None |
| RabbitMQ | `SquidStd.Messaging.RabbitMq` · `AddRabbitMqMessaging` | Self-hosted services, work queues | Per-queue | Durable queues | Run a broker |
| SQS/SNS | `SquidStd.Messaging.Sqs` · `AddSqsMessaging` | AWS-native, serverless | FIFO queues only | Managed, durable | Managed (AWS) |

```csharp
bootstrap.ConfigureServices(container => container.AddRabbitMqMessaging("amqp://localhost"));
```

## Recommendation

Use `AddInMemoryMessaging` for tests and single-process apps, `AddRabbitMqMessaging`
when you self-host, and `AddSqsMessaging` when you are already on AWS.
23 changes: 23 additions & 0 deletions docs/articles/guides/choosing-search-database.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Choosing search & database

Full-text search and relational persistence are different tools. Use the search
provider for queries over text and documents, and the database module (backed by
FreeSql) for structured, relational data.

| Need | Module · entrypoint | Provider(s) | Use case |
|---|---|---|---|
| Full-text / document search | `SquidStd.Search.Elasticsearch` · `AddElasticsearch` | Elasticsearch | Relevance ranking, faceting, log/document search |
| Relational data | `SquidStd.Database` · `RegisterDatabase` | FreeSql: Sqlite, PostgreSQL, MySql, SqlServer | Transactional records, joins, constraints |

The database provider is selected via `DatabaseProviderType` (`Sqlite`,
`PostgreSQL`, `MySql`, `SqlServer`) in the `database` config section.

```csharp
bootstrap.ConfigureServices(container => container.RegisterDatabase());
```

## Recommendation

Reach for `AddElasticsearch` when the core requirement is searching text or
documents by relevance; use `RegisterDatabase` with the FreeSql provider that
matches your engine for everything relational. They compose — many apps use both.
23 changes: 23 additions & 0 deletions docs/articles/guides/choosing-storage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Choosing a storage backend

The storage abstraction (`IStorageService`) stores blobs by key. There are two
providers; the S3 provider also targets any S3-compatible server such as MinIO.

| Backend | Package · entrypoint | Use case | Shared across hosts | Ops cost |
|---|---|---|---|---|
| Local file | `SquidStd.Storage` · `AddFileStorage` | Dev, single host, simple persistence | No | None |
| S3 | `SquidStd.Storage.S3` · `AddS3Storage` | AWS-native object storage | Yes | Managed (AWS) |
| MinIO | `SquidStd.Storage.S3` · `AddS3Storage` (set `ServiceUrl`) | Self-hosted S3-compatible storage | Yes | Run MinIO |

```csharp
bootstrap.ConfigureServices(container => container.AddS3Storage(new S3StorageOptions
{
// ServiceUrl points at AWS S3 or a self-hosted MinIO endpoint
}));
```

## Recommendation

Use `AddFileStorage` for development and single-host apps. Use `AddS3Storage`
against AWS S3 in the cloud, or against a MinIO endpoint (via `ServiceUrl`) when
you need S3 semantics on self-hosted infrastructure.
45 changes: 45 additions & 0 deletions docs/articles/guides/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Configuration

SquidStd loads configuration from a single YAML file. Each module registers a
strongly-typed section; the config manager deserializes it, expands environment
variables, and publishes the populated object into the container so you can
resolve it like any other service.

## Steps

1. **Point the bootstrap at your config file.** `SquidStdOptions.ConfigName` is the
logical file name (default `squidstd`, so `squidstd.yaml`) and
`RootDirectory` is the directory it is searched in.
2. **Register a section.** Call `RegisterConfigSection<TConfig>` with the section
name (the top-level YAML key). Provide a `createDefault` factory so the file
is generated with sensible defaults on first run.
3. **Use environment variables.** Any `string` property whose value contains a
`$VAR` token is expanded from the environment when the section is loaded.
Unknown tokens are left untouched.
4. **Read values.** Resolve the config type from the container wherever you need it.

```csharp
public sealed class MyServiceConfig
{
public string Endpoint { get; set; } = string.Empty; // e.g. "https://$API_HOST"
public int Retries { get; set; } = 3;
}

var bootstrap = SquidStdBootstrap.Create(
new SquidStdOptions { ConfigName = "squidstd", RootDirectory = AppContext.BaseDirectory });

bootstrap.ConfigureServices(container =>
container.RegisterConfigSection("myService", static () => new MyServiceConfig()));

await bootstrap.StartAsync();

var config = container.Resolve<MyServiceConfig>();
```

The corresponding `squidstd.yaml`:

```yaml
myService:
endpoint: "https://$API_HOST"
retries: 5
```
35 changes: 35 additions & 0 deletions docs/articles/guides/observability.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Observability

`SquidStd.Telemetry.OpenTelemetry` wires OpenTelemetry tracing and metrics into
the bootstrap as a managed service. Spans flow from SquidStd's own
`ActivitySource` instances and from anything else in your process.

## Steps

1. **Add the package** `SquidStd.Telemetry.OpenTelemetry`.
2. **Register telemetry** with `AddSquidStdTelemetry`, passing a `TelemetryOptions`
with your `ServiceName`.
3. **Choose an exporter.** Set `OtlpEndpoint` / `OtlpProtocol` to ship to a
collector (the default endpoint is `http://localhost:4317`, gRPC). For local
debugging set `EnableConsoleExporter = true` to also print spans to stdout.
4. **Tune sampling** with `TracingSampleRatio` (0..1) and toggle pipelines with
`EnableTracing` / `EnableMetrics`.

```csharp
bootstrap.ConfigureServices(container =>
container.AddSquidStdTelemetry(new TelemetryOptions
{
ServiceName = "orders-worker",
OtlpEndpoint = "http://otel-collector:4317",
OtlpProtocol = OtlpProtocolType.Grpc,
EnableConsoleExporter = false,
TracingSampleRatio = 1.0
}));
```

## ActivitySource convention

SquidStd modules name their `ActivitySource` instances with the `SquidStd.*`
prefix (for example `SquidStd.Messaging`). Subscribe to that prefix in your
collector or tracer-provider configuration to capture all framework spans, and
follow the same convention for your own application sources.
Loading
Loading