Skip to content

Commit c435a67

Browse files
authored
Merge pull request #13 from tgiachi/develop
Release: AWS secrets adapters, crypto VFS vault, docs overhaul, and audit hardening
2 parents 0e13908 + 3c3cd09 commit c435a67

189 files changed

Lines changed: 6753 additions & 735 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 181 additions & 25 deletions
Large diffs are not rendered by default.

SquidStd.slnx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737
<Project Path="src/SquidStd.Mail.Abstractions/SquidStd.Mail.Abstractions.csproj" />
3838
<Project Path="src/SquidStd.Mail.MailKit/SquidStd.Mail.MailKit.csproj" />
3939
<Project Path="src/SquidStd.Mail.Queue/SquidStd.Mail.Queue.csproj" />
40+
<Project Path="src/SquidStd.Crypto/SquidStd.Crypto.csproj" />
41+
<Project Path="src/SquidStd.Vfs.Abstractions/SquidStd.Vfs.Abstractions.csproj" />
42+
<Project Path="src/SquidStd.Vfs/SquidStd.Vfs.csproj" />
43+
<Project Path="src/SquidStd.Secrets.Aws/SquidStd.Secrets.Aws.csproj" />
4044
</Folder>
4145
<Folder Name="/samples/">
4246
<Project Path="samples/SquidStd.Samples.WorkerSystem/SquidStd.Samples.WorkerSystem.csproj" />
@@ -55,6 +59,10 @@
5559
<Project Path="samples/SquidStd.Samples.Caching/SquidStd.Samples.Caching.csproj" />
5660
<Project Path="samples/SquidStd.Samples.EventsJobsScheduling/SquidStd.Samples.EventsJobsScheduling.csproj" />
5761
<Project Path="samples/SquidStd.Samples.GettingStarted/SquidStd.Samples.GettingStarted.csproj" />
62+
<Project Path="samples/SquidStd.Samples.Crypto/SquidStd.Samples.Crypto.csproj" />
63+
<Project Path="samples/SquidStd.Samples.Vfs/SquidStd.Samples.Vfs.csproj" />
64+
<Project Path="samples/SquidStd.Samples.Secrets/SquidStd.Samples.Secrets.csproj" />
65+
<Project Path="samples/SquidStd.Samples.Actors/SquidStd.Samples.Actors.csproj" />
5866
</Folder>
5967
<Folder Name="/tests/">
6068
<Project Path="tests/SquidStd.Tests/SquidStd.Tests.csproj" />

docs/articles/actors.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[!include[](../../src/SquidStd.Actors/README.md)]
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Abstractions first
2+
3+
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.
4+
5+
## Contract package plus provider packages
6+
7+
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.
8+
9+
## In-memory for tests, external for prod
10+
11+
Most capabilities ship an in-memory provider for tests and an external-backend provider for production:
12+
13+
- **Messaging** — in-memory, or `SquidStd.Messaging.RabbitMq` / `SquidStd.Messaging.Sqs`.
14+
- **Caching** — in-memory, or `SquidStd.Caching.Redis`.
15+
- **Storage** — file-backed, or `SquidStd.Storage.S3` (S3 and MinIO).
16+
17+
Tests run fast and deterministically against the in-memory provider; production swaps in the external backend.
18+
19+
## Swapping providers without touching call sites
20+
21+
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.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Architecture
2+
3+
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.
4+
5+
## Modular by design
6+
7+
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.
8+
9+
## Layers
10+
11+
The dependency flow runs in one direction:
12+
13+
- **Core** (`SquidStd.Core`) — primitives, options, and the building blocks everything else sits on.
14+
- **Abstractions** — per-capability contract packages.
15+
- **Providers** — concrete implementations of those contracts.
16+
- **Host**`SquidStdBootstrap` composes services and runs them.
17+
18+
Higher layers depend on lower ones, never the reverse.
19+
20+
## Package graph
21+
22+
```mermaid
23+
graph TD
24+
Core[SquidStd.Core] --> Services[SquidStd.Services.Core]
25+
Abstr[*.Abstractions contracts] --> Providers[Provider packages]
26+
Services --> Host[SquidStdBootstrap host]
27+
Providers --> Host
28+
Host --> App[Your application]
29+
```
30+
31+
## Next
32+
33+
- [Bootstrap lifecycle](bootstrap-lifecycle.md) — how the host starts and stops services.
34+
- [Abstractions first](abstractions-first.md) — the contract-plus-provider pattern in depth.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Bootstrap lifecycle
2+
3+
`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.
4+
5+
## Create
6+
7+
Begin by creating the bootstrap from `SquidStdOptions`:
8+
9+
```csharp
10+
var bootstrap = SquidStdBootstrap.Create(new SquidStdOptions
11+
{
12+
ConfigName = "squidstd",
13+
RootDirectory = AppContext.BaseDirectory
14+
});
15+
```
16+
17+
`ConfigName` selects the configuration file and `RootDirectory` anchors relative paths.
18+
19+
## ConfigureServices
20+
21+
Register your services into the DryIoc container:
22+
23+
```csharp
24+
bootstrap.ConfigureServices(container =>
25+
{
26+
container.AddSomething();
27+
});
28+
```
29+
30+
See [dependency injection](dependency-injection.md) for the container and the `AddXxx` / `RegisterXxx` pattern.
31+
32+
## Start and stop over ISquidStdService
33+
34+
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.
35+
36+
```mermaid
37+
sequenceDiagram
38+
participant App
39+
participant Bootstrap as SquidStdBootstrap
40+
participant Svc as ISquidStdService(s)
41+
App->>Bootstrap: Create(options)
42+
App->>Bootstrap: ConfigureServices(container)
43+
App->>Bootstrap: StartAsync()
44+
Bootstrap->>Svc: StartAsync() (in order)
45+
App->>Bootstrap: StopAsync()
46+
Bootstrap->>Svc: StopAsync() (reverse order)
47+
```
48+
49+
## RunAsync for long-running hosts
50+
51+
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.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Dependency injection
2+
3+
SquidStd resolves every service through dependency injection. Understanding the container and its registration pattern is the key to wiring an application together.
4+
5+
## DryIoc container
6+
7+
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.
8+
9+
## The AddXxx / RegisterXxx extension pattern
10+
11+
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:
12+
13+
```csharp
14+
container.AddInMemoryMessaging();
15+
container.RegisterCoreServices();
16+
```
17+
18+
This keeps registration discoverable and colocated with the package that owns it.
19+
20+
## Resolving through the bootstrap
21+
22+
Once configured, resolve services through the bootstrap:
23+
24+
```csharp
25+
var bus = bootstrap.Resolve<IEventBus>();
26+
```
27+
28+
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.
29+
30+
## Singletons and lifecycle
31+
32+
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.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Messaging models
2+
3+
SquidStd offers three in-process messaging models. Each fits a different shape of communication, and they can be mixed freely within one application.
4+
5+
## Event Bus
6+
7+
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.
8+
9+
## Command Dispatcher
10+
11+
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.
12+
13+
## Actors
14+
15+
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.
16+
17+
## Choosing
18+
19+
```mermaid
20+
flowchart TD
21+
Q{Need ordered, per-entity state?} -->|yes| A[Actors]
22+
Q -->|no| R{Request → single handler with a result?}
23+
R -->|yes| C[Command Dispatcher]
24+
R -->|no| E[Event Bus broadcast]
25+
```
26+
27+
All three are contract-first; see [abstractions first](abstractions-first.md) for swapping in external transports.

docs/articles/crypto.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[!include[](../../src/SquidStd.Crypto/README.md)]

docs/articles/getting-started.md

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,19 @@ dotnet add package SquidStd.Services.Core
77
```
88

99
```csharp
10-
using DryIoc;
11-
using SquidStd.Services.Core.Extensions;
10+
using SquidStd.Core.Data.Bootstrap;
11+
using SquidStd.Services.Core.Services.Bootstrap;
1212

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

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

19-
From here, add focused packages as needed — see the per-package guides in the sidebar and the
20-
[API reference](../api/index.md).
23+
Opt into modules with `ConfigureServices`, e.g. `container.AddInMemoryCache()`. See the
24+
[Concepts](concepts/bootstrap-lifecycle.md) for the full lifecycle and
25+
[Packages](getting-started.md) for per-module reference.

0 commit comments

Comments
 (0)