Conversation
Promote VfsPath to SquidStd.Vfs.Abstractions (public) so the crypto decorator and the VFS providers share identical path normalization.
- KmsSecretProtector implements ISecretProtector via AWS KMS data keys - KmsEnvelope frames [wrappedKeyLen|wrappedKey|nonce|tag|ciphertext] with AES-GCM - zero the plaintext data key after sealing/opening; dispose owns KMS client - LocalStack-backed integration test round-trips a >4KB payload
- AwsSecretsManagerStore implements ISecretStore over AWS Secrets Manager - Set upserts via PutSecretValue, falling back to CreateSecret when absent - Delete gates on existence so a missing secret returns false on both real AWS and LocalStack - ListNamesAsync paginates ListSecrets and strips the configured NamePrefix - store disposes its Secrets Manager client - LocalStack-backed integration test covers the full set/get/exists/list/delete cycle
Demonstrate IPgpKeyring.SaveAsync to the file-backed store and a fresh PgpKeyring.LoadAsync round-trip, instead of registering a key store that was never used. Clarify the PrivateArmored null-forgiving operator.
Drive CryptoFileSystem over an in-memory backend through the full unlock/write/lock/reopen lifecycle so the encrypted round-trip is real, and document that the RegisterCryptoVault disk backend (ZipFileSystem) cannot currently be locked due to a ZipArchive Update-mode limitation.
Professional documentation overhaul (Diátaxis on DocFX): - rewrite landing + getting-started - add reference articles + normalise all 41 package READMEs to a uniform template - add 5 Concept pages with Mermaid diagrams, 4 how-to + 4 provider decision guides - add 4 compiling sample projects (Crypto/Vfs/Secrets/Actors) and 6 tutorials - full link/diagram audit; every package has README + article + TOC entry # Conflicts: # src/SquidStd.Actors/README.md # src/SquidStd.Generators/README.md # src/SquidStd.Messaging.Sqs/README.md
- ZipFileSystem.ListAsync no longer reads ZipArchiveEntry.Length (unavailable in ZipArchiveMode.Update for entries written this session); track uncompressed sizes in a dictionary on write/delete and fall back safely so listing never throws - CryptoFileSystem.Dispose now disposes its inner filesystem after Lock(), so a ZipFileSystem backend flushes its archive to disk and the vault persists - this fixes RegisterCryptoVault throwing InvalidOperationException on Lock()/Dispose() via PruneOrphans(), which made on-disk encrypted vaults unusable - add ZipFileSystem.ListAsync same-session test and disk-backed CryptoFileSystem lock + cross-instance persistence tests (previously untested: tests used InMemoryFileSystem) - update the Vfs sample and tutorial to demonstrate real on-disk vault persistence
Fix on-disk crypto vault: ZipFileSystem.ListAsync no longer crashes on ZipArchiveEntry.Length in update mode, and CryptoFileSystem.Dispose flushes its inner filesystem so RegisterCryptoVault persists to disk.
…e actor dispose race-safe - crypto: bound the unauthenticated per-record length prefix in EntryCipher.DecryptAsync against the configured chunk size before allocating, so a corrupt or tampered vault cannot trigger OOM or a negative-size crash - crypto: reject VaultBlob payloads shorter than nonce+tag instead of producing an opaque negative-length slice on a truncated index - crypto: make VaultIndex thread-safe (lock around Set/TryGet/Remove/Serialize, Entries returns a point-in-time snapshot) so concurrent vault operations cannot corrupt the map - vfs: InMemoryFileSystem.ReadAllBytesAsync returns a copy so callers mutating what they read no longer corrupt the stored bytes - vfs: PhysicalFileSystem.Resolve validates the resolved path stays within the root, rejecting segments that escape it (e.g. drive-rooted segments on Windows) - vfs: delete the dead duplicate SquidStd.Vfs/Internal/VfsPath.cs (unreferenced) - actors: claim the dispose guard atomically (Interlocked) and read it via Volatile so concurrent double-dispose cannot both run teardown
…P, retry failed declares - persistence: replay each journal entry against its own type's snapshot watermark instead of a single global maximum, so a partial snapshot save (one bucket persisted, another not) no longer silently drops the lagging type's journaled writes on the next startup - persistence: discard journal records whose framed length is smaller than the fixed entry header as a truncated tail, instead of letting the decoder crash startup - network: clear the UDP server's endpoint→listener routes on Stop so a later Start cannot send through a stale, disposed socket - network: mark a UDP session's connection closed when it is removed by the idle sweep, so holders observe IsConnected == false (CloseAsync stays idempotent for the explicit-close path) - rabbitmq: only keep a queue/exchange marked as declared when the declare succeeds; undo the optimistic mark on failure so a later call retries instead of assuming the topology exists
Previously DisposeAsync cancelled the shutdown token before completing the mailbox. Because the mailbox was bound to that token, cancelling first aborted the block and silently discarded any queued fire-and-forget messages. - decouple the mailbox from the shutdown token so completing it drains the queue rather than aborting - DisposeAsync now completes the mailbox and drains queued work (Tells run, Asks reply) within the new ActorOptions.ShutdownDrainTimeout (default 5s); on timeout it cancels in-flight handlers, grants a brief grace period, then faults any still-pending requests with ObjectDisposedException - add ActorOptions.ShutdownDrainTimeout - document the new shutdown contract in the Actors README
…n in memory Upsert/Remove now build the entry and append it durably before mutating the in-memory bucket and committing LastSequenceId. A failed append leaves memory and the sequence counter untouched, so they never diverge from what journal replay would rebuild.
…ot interleave Wrap the whole snapshot operation (capture, save, delete-empty, trim) in a dedicated lock so autosave, an explicit call, and StopAsync can no longer interleave their save/trim phases and regress a snapshot below an already-trimmed journal sequence.
…payload New snapshots are Version 2 with a checksum covering Version, LastSequenceId, TypeId, TypeName, SchemaVersion and Payload, so a corrupted sequence field is now detected. Version 1 files keep loading under the legacy payload-only checksum. Adds a two-span FNV overload to ChecksumUtils.
… writes In DurabilityMode.Durable the journal opens its append stream WriteThrough and flushes to disk after each write/batch, and the snapshot fsyncs its temp file before the atomic rename. Buffered (default) keeps the current OS-cache flush. Documents the option and its portability limit.
…egacy names
Snapshot files are now named snake(typeName)_{typeId}{suffix}, so two type names that snake-case to the
same string no longer collide. LoadBucketAsync renames a legacy (pre-TypeId) file to the new scheme on
first access; DeleteBucketAsync removes both forms. ISnapshotService Load/Delete gain a typeId parameter.
…d buffering Add a configurable maxFrameLength (default 1 MiB), propagated from SquidTcpServer to each accepted client. When the pending buffer exceeds the cap without completing a frame, or a framer reports an oversized frame, the connection is closed before the buffer grows further.
Contributor
There was a problem hiding this comment.
CodeQL found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Release of everything accumulated on
developsince the lastmaincut. Three themes: new modules, a full documentation overhaul, and a multi-batch robustness/security audit remediation.New features
RegisterKmsSecretProtector/RegisterAwsSecretsManagerStoreDI extensions. AddsISecretStore.ListNamesAsync(+FileSecretStore).IVirtualFileSystem; on-disk vault now persists correctly.PersistenceConfig.DurabilityMode(Buffereddefault /Durable):Durablefsyncs journal appends and snapshot temp files before the atomic rename.Documentation
#regionstep markers.Audit remediation (robustness, durability, security)
ListAsynccrash fix.ShutdownDrainTimeoutinstead of dropping them; race-safe dispose guard.MaxFrameLength(1 MiB) to bound per-connection buffering; UDP listener/route cleanup on stop; session marked closed on idle sweep.Test plan
dotnet build SquidStd.slnx -c Debug— 0 errorsDurabilityModedefaults toBuffered