Skip to content

Commit e5806f9

Browse files
committed
feat(WP-1.R): retire the v2 core and EF stores, redaction wiring
Satisfies every plan 07 row for the v2 core and EF store suites, then deletes src/SourceFlow, src/SourceFlow.Stores.EntityFramework and their v2 tests (WP-1.R, WP-2.R). E2E-08 (rebuild) is tracked under WP-4.1. - Subscriptions: Stop failure policy (the projection default) with capped backoff, a halted partition, sourceflow.subscription.stalled and an audited ISubscriptionAdmin.SkipAsync; OnFailure(...) per projection; Park stays the default for process managers and handlers. - Projections: DC-2 on-read version guard, so re-applied events don't double-count incremental documents. - Dead letters: show, purge, type and date filters, replay and discard metrics. - Envelopes no longer keep a caller's mutable header dictionary. - WP-5.3 redaction: SourceFlow taxonomy, [PersonalData] and [Secret] as data classifications, Erasing redactor by default (HMAC optional), LogPayloads with classified members redacted. - Tests: UT-CMD, UT-MW-06..20, UT-RX-17..19, UT-DLQ-01..10, UT-HOST-03..08, UT-RT-15..20, UT-MSG-29/30, UT-STO-09, UT-SUB-02..13, UT-PRJ-02..06, UT-PM-02..13, UT-EF-05..10, UT-RED-01..06.
1 parent 08504a6 commit e5806f9

210 files changed

Lines changed: 1755 additions & 16264 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.

‎Directory.Packages.props‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.15" />
1010
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.15" />
1111
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.15" />
12+
<PackageVersion Include="Microsoft.Extensions.Compliance.Abstractions" Version="10.0.0" />
13+
<PackageVersion Include="Microsoft.Extensions.Compliance.Redaction" Version="10.0.0" />
1214
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" Version="10.0.15" />
1315
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="10.0.15" />
1416
<PackageVersion Include="System.IO.Hashing" Version="10.0.0" />

‎docs/v3.0.0/implementation/07-V2-Test-Disposition-Matrix.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ Every v2 test file gets exactly one disposition. The retirement work packages (W
1111

1212
## 1. `tests/SourceFlow.Core.Tests` (NUnit, 237 tests, 28 files) → WP-1.R
1313

14+
**Retired 2026-11-11.** Every named v3 test exists and passes, except two:
15+
16+
- **E2E-08:** projection rebuild. The v2 replay concept moves to the blue/green rebuild, which ships with the CLI (WP-4.1) and is tracked there.
17+
- **SCK-36:** covered by SCK-34.
18+
19+
`src/SourceFlow` and this project are deleted. The v2 cloud projects that reference `src/SourceFlow` (`src/SourceFlow.Cloud.AWS`, `src/SourceFlow.Cloud.GCP`) remain only as reference input for M3 and are deleted by WP-3.R.
20+
1421
| v2 file (tests) | Disposition | v3 tests | Notes |
1522
|-----------------|-------------|----------|-------|
1623
| `E2E/E2E.Tests` (1 scenario) | **Port** | E2E-01, E2E-02, E2E-08 | The bank-account domain becomes `samples/Bank` (WP-1.14). Replay becomes a rebuild |
@@ -44,6 +51,8 @@ Every v2 test file gets exactly one disposition. The retirement work packages (W
4451

4552
## 2. `tests/SourceFlow.Stores.EntityFramework.Tests` (NUnit, 52 tests, 7 files) → WP-2.R
4653

54+
**Retired 2026-11-11.** Every named v3 test exists and passes. SCK cases run on in-memory, PostgreSQL and PostgreSQL with RLS, and UT-EF-01..10 run on PostgreSQL. E2E-08 follows with the rebuild tooling (WP-4.1). `src/SourceFlow.Stores.EntityFramework` and this project are deleted.
55+
4756
| v2 file (tests) | Disposition | v3 tests | Notes |
4857
|-----------------|-------------|----------|-------|
4958
| `E2E/E2E.Tests` (1 scenario) | **Port** | E2E-01, 02, 08 on PostgreSQL (and SQL Server from M4) | |

‎docs/v3.0.0/implementation/STATUS.md‎

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ Updated in the PR that completes a work package (CONTRIBUTING.md). Status values
44

55
## Progress summary
66

7-
Updated 2026-11-11. **29 of 63 work packages are done (46%)**, 1 in progress and 33 not started. By estimated effort, 59.5 of 138.5 engineer-weeks are done (43%).
7+
Updated 2026-11-11. **32 of 63 work packages are done (51%)**, 1 in progress and 30 not started. By estimated effort, 61 of 138.5 engineer-weeks are done (44%).
88

99
| Milestone | Done | In progress | Todo | Effort done (ew) |
1010
|-----------|------|-------------|------|------------------|
1111
| M0 Foundations | 5 | 0 | 0 | 4 of 4 |
12-
| M1 Core | 14 | 0 | 1 | 36.5 of 37 |
13-
| M2 PostgreSQL | 9 | 1 | 1 | 16.5 of 19 |
12+
| M1 Core | 15 | 0 | 0 | 37 of 37 |
13+
| M2 PostgreSQL | 10 | 1 | 0 | 17 of 19 |
1414
| M3 Cloud transports | 0 | 0 | 7 | 0 of 19 |
1515
| M4 Tooling and operations | 1 | 0 | 6 | 2.5 of 16.5 |
16-
| M5 Security and migration | 0 | 0 | 5 | 0 of 11 |
16+
| M5 Security and migration | 1 | 0 | 4 | 0.5 of 11 |
1717
| Track S: Workflow DSL and Studio | 0 | 0 | 13 | 0 of 32 |
1818

1919
Completed in this round:
@@ -25,12 +25,14 @@ Completed in this round:
2525
- WP-1.14: the Bank.Api host, the Studio demo console, the docker-compose demo, and images on ghcr.io.
2626
- WP-4.2: the production query API and domain queries over HTTP.
2727
- WP-2.8: PostgreSQL index sync for `[Queryable]` fields.
28+
- WP-1.R and WP-2.R: v2 core and v2 EF stores retired after every plan 07 row was satisfied. This needed about 80 new v3 tests, the Stop subscription policy, the DC-2 guard, and dead-letter show/purge/filters.
29+
- WP-5.3: redaction wiring (taxonomy, Erasing/HMAC redactors, `LogPayloads`).
2830

2931
Still in progress:
3032

3133
- WP-2.7 (`SourceFlow.Storage.EntityFrameworkCore` read models): rebuilding a projection into a new schema, which waits for the blue/green rebuild tooling.
3234

33-
Not started: the v2 retirements (1.R, 2.R, 3.R), every cloud transport (M3), the CLI, health and dashboards, SQL Server, event partitioning, chaos and load testing, payload protection, crypto-shredding, the v2 migration tool, and the whole Studio track.
35+
Not started: the v2 cloud retirement (3.R), every cloud transport (M3), the CLI, health and dashboards, SQL Server, event partitioning, chaos and load testing, payload protection, crypto-shredding (redaction is done), the v2 migration tool, and the whole Studio track.
3436

3537
| WP | Title | Estimate (ew) | Status | Notes |
3638
|----|-------|---------------|--------|-------|
@@ -47,13 +49,13 @@ Not started: the v2 retirements (1.R, 2.R, 3.R), every cloud transport (M3), the
4749
| WP-1.6 | Command processing + temporal reads | 3 | done | CommandProcessor, CommandSender, AggregateReader (AsOf), snapshots (interval, schema hash); the aggregate cache landed with WP-2.5 |
4850
| WP-1.7 | Middleware and diagnostics | 1.5 | done | MessagePipeline, built-in middleware, ErrorClassifier, SourceFlowMetrics with InstrumentAdvice; UT-MW |
4951
| WP-1.8 | Outbox, scheduler, transport SPI, in-memory broker, receive pipeline | 3.5 | done | Transport SPI, InMemoryBroker, OutboxRelay, ReceiveEndpoint, dead letters; TCK-01..12 green on the in-memory broker |
50-
| WP-1.9 | Subscriptions, projections, process managers, event handlers | 4 | done | SubscriptionEngine (fenced, partitioned, adaptive batches, park policy with per-event isolation), projections, process managers (incl. `CommandRejected<T>` replies: `sf-reply-to` header for local owners and `ReplyOnReject()` routes, reply committed with the rejection, ADR-018), event handlers; `INodeRegistry` heartbeat + fair-share rebalancer (one lease released per pass, graceful hand-back on stop). UT-SUB-01/05/06/08/09/10/12/17, UT-PRJ-01, UT-PM-01/10..13, E2E-09..15. Repartition and blue/green rebuild (UT-SUB-21..28) and the `projection skip` Stop policy come with the CLI (WP-4.1) |
52+
| WP-1.9 | Subscriptions, projections, process managers, event handlers | 4 | done | SubscriptionEngine (fenced, partitioned, adaptive batches, park policy with per-event isolation), projections, process managers (incl. `CommandRejected<T>` replies: `sf-reply-to` header for local owners and `ReplyOnReject()` routes, reply committed with the rejection, ADR-018), event handlers; `INodeRegistry` heartbeat + fair-share rebalancer (one lease released per pass, graceful hand-back on stop). Stop policy (projection default: backoff, halted partition, `sourceflow.subscription.stalled`, audited `ISubscriptionAdmin.SkipAsync`) and Park policy; DC-2 on-read version guard. UT-SUB-01..13, 17, UT-PRJ-01..06, UT-PM-01..13, E2E-09..15. Repartition and blue/green rebuild (UT-SUB-21..28) come with the CLI (WP-4.1) |
5153
| WP-1.10 | Hosting, roles, tenancy context | 1.5 | done | AddSourceFlow, SourceFlowBuilder Use* slots, roles, SourceFlowHost lifecycle, health check |
5254
| WP-1.11 | `SourceFlow.Testing` | 2.5 | done | SourceFlowTestHost, AggregateSpec, ProcessManagerSpec, ProjectionSpec, approvals; UT-TST |
5355
| WP-1.12 | Schema catalog | 2 | done | JSON Schema 2020-12 per message type and version, read-model document and process state, derived from the serializer's JsonTypeInfo with `x-sourceflow-*` extensions (ADR-029); canonical text + SHA-256 fingerprints; `ISchemaStore` (in-memory, PostgreSQL `schemas`) registered at startup, a changed published `(type, version)` fails startup (`SchemaRegistration` = Enforce/Warn/Off); lock file; `SchemaCompatibility` rules SFC01–SFC10; AsyncAPI 3.0 exporter. UT-CAT-01..18 |
5456
| WP-1.13 | SFQL front end (pipeline + SQL syntax) + in-memory interpreter + domain queries | 5.5 | done | Request guard, lexer, both parsers into one AST; catalog, binder, policy (SFQ0101–0602); in-memory interpreter and `IQueryService` (typed parameters, PII redaction, tenancy, keyset continuation, `at_least` waits, plan cache, `IQueryEngine` SPI); named domain queries (`[DomainQuery]`, generated runtime, `ExecuteAsync`, startup binding, ADR-030); typed builder (`Events<T>()`, `ReadModel<T>()`); analyzers SF0015/SF0016/SF0018. UT-QL-01..95, GEN-47..50; PostgreSQL compiler in WP-2.8 |
5557
| WP-1.14 | Bank sample (ported v2 E2E domain) | 1.5 | done | Bank.Contracts/Accounts/Transfers/Notifications + E2E-01..07, 11, 13, 14, 17..20 green; Bank.Api host (commands, demo query endpoints), Studio demo console, docker-compose demo and ghcr.io images (`v3-images` workflow) |
56-
| WP-1.R | Retire v2 core | 0.5 | todo | |
58+
| WP-1.R | Retire v2 core | 0.5 | done | Every `SourceFlow.Core.Tests` row in plan 07 is satisfied: v3 suites for commands, middleware and built-ins, dead letters, hosting, options, subscriptions, projections (incl. the DC-2 on-read version guard) and process managers, plus redaction (WP-5.3). E2E-08 (rebuild) is tracked under WP-4.1. `src/SourceFlow` and `tests/SourceFlow.Core.Tests` are deleted; the v2 cloud projects that still reference it go with WP-3.R |
5759
| WP-2.1 | PostgreSQL schema and migrator | 1.5 | done | V001 schema (ADR-028: json payload columns, tenant columns), PostgreSqlSchemaMigrator (advisory lock, checksummed schema_history, db script), UsePostgreSql with AutoMigrate (Development only by default); SCK-M01..M06. V002 (RLS) and V003 (partitioned events) come with WP-2.6 and WP-4.5 |
5860
| WP-2.2 | PostgreSQL append and stream read | 2 | done | Write-behind session (one NpgsqlBatch, append first; ES-R1/ES-R2), CTE append for all ExpectedVersion kinds, conflict and closed-stream diagnosis, single-statement stream read; SCK-01..19 green. Commit is batch + COMMIT (two round trips; folding COMMIT in is WP-2.10) |
5961
| WP-2.3 | Global log reader and notifications | 1.5 | done | (tx_id, seq) read below pg_snapshot_xmin with bucket filter, inclusive horizon, GetHorizonAgeAsync; LISTEN/NOTIFY with origin filtering, reconnect, ListenConnectionString; SCK-21..28 incl. SCK-24 (32 writers) and the held-horizon test. Wiring horizon_age into metrics/health is WP-4.3 |
@@ -64,7 +66,7 @@ Not started: the v2 retirements (1.R, 2.R, 3.R), every cloud transport (M3), the
6466
| WP-2.8 | SFQL on PostgreSQL (incl. joins and grouping) + index sync + domain queries | 3.5 | done | PostgreSqlQueryEngine (`IQueryEngine`): one parameterised statement per page (every request value a typed `$n` parameter, I-3), keyset predicate and ORDER BY outside a derived table, `COLLATE "C"` text ordering, horizon predicate, per-version rename CASE, tenant predicates (G-9), `NULLIF` division, read-only transaction with `statement_timeout` (`QueryTimeout`, default 5 s) and the RLS tenant setting; aggregate and schema sources stay in the interpreter. Cross-provider equivalence with the interpreter on the same data (QRY-01..20, incl. joins, grouping/having, distinct, subqueries, keyset pages interchangeable between engines), golden SQL (QRY-42/43), injection corpus (QRY-44), no-literal CsCheck property (QRY-60). Catalog now types enums by their JSON (number or string). Domain queries run through the engine (ExecuteAsync and `/queries`). `/query/explain` shows the parameterised SQL. `PostgreSqlIndexSync` (plan/apply, CONCURRENTLY by default): one partial expression index per `[Queryable]` field over `events` (per type) and `documents` (per collection), using the compiler's exact expression, `sfq_` hash names, stale ones dropped; QRY-45 shows the planner using it. The CLI command (`db index sync`) is WP-4.1 |
6567
| WP-2.9 | Storage conformance kit complete | 2 | done | SCK-01..58 in SourceFlow.Testing, run on in-memory, PostgreSQL and PostgreSQL with RLS. New in this package: SCK-23 (in-flight writes invisible), SCK-37 (batched retention via IStoreRetention, plus the host retention loop), SCK-54 (CsCheck property: snapshot + tail = full fold), PostgreSQL SCK-28 (LISTEN loss and reconnect), and SCK-L01 CsCheck linearisability of appends and the outbox. SCK-36 is covered by SCK-34. SCK-20 (one round trip) moves to WP-2.10, and SCK-65..72 (partitioned events) to WP-4.5 |
6668
| WP-2.10 | Performance baseline | 1 | done | benchmarks/SourceFlow.Benchmarks (BenchmarkDotNet PERF-01..04, 06; measurement harness PERF-05, 08, 10); baselines in benchmarks/baselines and the report in implementation/perf-baseline.md. One-round-trip PostgreSQL commit (SCK-20), batch-aware document projections and adaptive subscription batches. Deviations logged with owners (PERF-01/02 allocations, PERF-10 borderline). PERF-07 waits for M3 and PERF-09 for WP-4.7 |
67-
| WP-2.R | Retire v2 EF stores | 0.5 | todo | |
69+
| WP-2.R | Retire v2 EF stores | 0.5 | done | Every `SourceFlow.Stores.EntityFramework.Tests` row is satisfied (SCK on three adapters, UT-EF-01..10). `src/SourceFlow.Stores.EntityFramework` and its tests are deleted |
6870
| WP-3.1 | Transport SPI final + Transport Conformance Kit | 3 | todo | |
6971
| WP-3.2 | `SourceFlow.Cloud.Aws` | 4 | todo | |
7072
| WP-3.3 | `SourceFlow.Cloud.Gcp` | 3.5 | todo | |
@@ -81,7 +83,7 @@ Not started: the v2 retirements (1.R, 2.R, 3.R), every cloud transport (M3), the
8183
| WP-4.7 | Chaos suite + tier-M load test | 2.5 | todo | |
8284
| WP-5.1 | Payload protection + KMS key providers | 3 | todo | |
8385
| WP-5.2 | Crypto-shredding | 3 | todo | |
84-
| WP-5.3 | Redaction wiring | 0.5 | todo | |
86+
| WP-5.3 | Redaction wiring | 0.5 | done | SourceFlow taxonomy (`SourceFlowTaxonomy.PersonalData`/`Secret`); `[PersonalData]` and `[Secret]` are `DataClassificationAttribute`s; `UseRedaction(...)` with Erasing as the default and HMAC as an option; `LogPayloads` (off by default) logs parked payloads with classified members redacted. UT-RED-01..06 |
8587
| WP-5.4 | v2 migration tool + v2 wire bridge | 3 | todo | |
8688
| WP-5.5 | Fuzzing + security review | 1.5 | todo | |
8789
| WP-S.1 | Static manifest emission | 2 | todo | |

‎src/Core/SourceFlow.Net/Diagnostics/Log.cs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ internal static partial class Log
2929
[LoggerMessage(1105, LogLevel.Information, "Retention cleanup deleted {Inbox} inbox rows and {DeadLetters} resolved dead letters")]
3030
public static partial void RetentionPurged(ILogger logger, int inbox, int deadLetters);
3131

32+
[LoggerMessage(1108, LogLevel.Debug, "Payload of parked message {MessageId}: {Payload}")]
33+
public static partial void ParkedPayload(ILogger logger, string messageId, string payload);
34+
3235
[LoggerMessage(1107, LogLevel.Warning, "Schema {Type} v{Version} changed without a new version (registered {Registered}, now {Current}); a published version is immutable")]
3336
public static partial void SchemaConflict(ILogger logger, string type, int version, string registered, string current);
3437

@@ -47,6 +50,9 @@ internal static partial class Log
4750
[LoggerMessage(1301, LogLevel.Error, "Subscription {Subscription} partition {Partition} failed on event {EventId}; {Policy}")]
4851
public static partial void SubscriptionFailed(ILogger logger, Exception exception, string subscription, int partition, string eventId, string policy);
4952

53+
[LoggerMessage(1303, LogLevel.Warning, "Subscription {Subscription} partition {Partition} skipped event {EventId} at {Position}: {Reason}")]
54+
public static partial void SubscriptionSkipped(ILogger logger, string subscription, int partition, string eventId, string position, string reason);
55+
5056
[LoggerMessage(1302, LogLevel.Warning, "Subscription {Subscription} partition {Partition} lost its lease")]
5157
public static partial void SubscriptionLeaseLost(ILogger logger, string subscription, int partition);
5258

‎src/Core/SourceFlow.Net/Diagnostics/SourceFlowTelemetry.cs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ public SourceFlowMetrics()
8989
SnapshotsDropped = Meter.CreateCounter<long>("sourceflow.snapshot.dropped", "{snapshot}", "Snapshots dropped because the queue was full or the write failed.");
9090
RetryAttempts = Meter.CreateCounter<long>("sourceflow.retry.attempts", "{attempt}", "Retry attempts.");
9191
DeadLettersParked = Meter.CreateCounter<long>("sourceflow.deadletter.parked", "{message}", "Messages parked to dead letters.");
92+
DeadLettersReplayed = Meter.CreateCounter<long>("sourceflow.deadletter.replayed", "{message}", "Dead letters replayed by an operator.");
93+
DeadLettersDiscarded = Meter.CreateCounter<long>("sourceflow.deadletter.discarded", "{message}", "Dead letters discarded by an operator.");
9294
SubscriptionBatchDuration = Meter.CreateHistogram("sourceflow.subscription.batch.duration", "s", "Subscription batch duration.", tags: null, advice: duration);
9395
SentMessages = Meter.CreateCounter<long>("messaging.client.sent.messages", "{message}", "Messages sent to the broker.");
9496
ConsumedMessages = Meter.CreateCounter<long>("messaging.client.consumed.messages", "{message}", "Messages received from the broker.");
@@ -126,6 +128,10 @@ public SourceFlowMetrics()
126128

127129
public Counter<long> DeadLettersParked { get; }
128130

131+
public Counter<long> DeadLettersReplayed { get; }
132+
133+
public Counter<long> DeadLettersDiscarded { get; }
134+
129135
public Histogram<double> SubscriptionBatchDuration { get; }
130136

131137
public Counter<long> SentMessages { get; }

‎src/Core/SourceFlow.Net/Domain/Attributes.cs‎

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,30 @@ public SourceFlowModuleAttribute(Type? jsonContext = null)
9292
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Field, Inherited = false)]
9393
public sealed class AggregateIdAttribute : Attribute;
9494

95-
/// <summary>Marks a member as personal data: encrypted per subject and erasable (doc 10 §4).</summary>
95+
/// <summary>
96+
/// Marks a member as personal data: encrypted per subject and erasable (doc 10 §4), and classified as
97+
/// <see cref="SourceFlowTaxonomy.PersonalData"/> so logs and telemetry redact it (doc 10 §5).
98+
/// </summary>
99+
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Field, Inherited = false)]
100+
public sealed class PersonalDataAttribute : Microsoft.Extensions.Compliance.Classification.DataClassificationAttribute
101+
{
102+
/// <summary>Marks the member.</summary>
103+
public PersonalDataAttribute()
104+
: base(SourceFlowTaxonomy.PersonalData)
105+
{
106+
}
107+
}
108+
109+
/// <summary>Marks a member as a secret (tokens, keys): always redacted in logs and telemetry (doc 10 §5).</summary>
96110
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Field, Inherited = false)]
97-
public sealed class PersonalDataAttribute : Attribute;
111+
public sealed class SecretAttribute : Microsoft.Extensions.Compliance.Classification.DataClassificationAttribute
112+
{
113+
/// <summary>Marks the member.</summary>
114+
public SecretAttribute()
115+
: base(SourceFlowTaxonomy.Secret)
116+
{
117+
}
118+
}
98119

99120
/// <summary>Makes a member indexed and filterable in SFQL (DM-R6).</summary>
100121
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Field, Inherited = false)]
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using Microsoft.Extensions.Compliance.Classification;
2+
3+
namespace SourceFlow;
4+
5+
/// <summary>
6+
/// SourceFlow's data classification taxonomy (doc 10 §5), wired to Microsoft.Extensions.Compliance.Redaction:
7+
/// <c>[PersonalData]</c> members are <see cref="PersonalData"/>, <c>[Secret]</c> members are <see cref="Secret"/>.
8+
/// </summary>
9+
public static class SourceFlowTaxonomy
10+
{
11+
/// <summary>The taxonomy name.</summary>
12+
public const string TaxonomyName = "SourceFlow";
13+
14+
/// <summary>Personal data: redacted in logs and telemetry, encrypted per subject in storage.</summary>
15+
public static DataClassification PersonalData { get; } = new(TaxonomyName, nameof(PersonalData));
16+
17+
/// <summary>Secrets: always redacted.</summary>
18+
public static DataClassification Secret { get; } = new(TaxonomyName, nameof(Secret));
19+
20+
/// <summary>Both classifications.</summary>
21+
public static DataClassificationSet All { get; } = new(PersonalData, Secret);
22+
}

0 commit comments

Comments
 (0)