docs(comments): strip internal task/milestone/bundle bookkeeping from code comments
Remove project bookkeeping citations from shipped code comments across the solution: hyphenated task IDs (WP-14, StoreAndForward-025), milestone/task/ issue refs (M3, Task 4, Audit Log #23, #21), Bundle X task-bundle labels, and C/D/K/S/T phase labels. Comment text only — no code logic, string/log literals, or XML-doc structure changed. Genuine descriptions are preserved (only the citation is stripped), and technical lookalikes are retained (UTF-8, SHA-256, T00:00:00, M365, UTC-5, pre-C4/pre-C5 schema versions). Flagged by the new CommentChecker TaskReferenceInComment / TrackingReferenceInComment checks plus targeted grep passes; full solution builds clean, append-only guard tests pass.
This commit is contained in:
@@ -10,7 +10,7 @@ namespace ZB.MOM.WW.ScadaBridge.Transport.Serialization;
|
||||
/// <b>Important — unknown-property tolerance:</b>
|
||||
/// <see cref="JsonUnmappedMemberHandling"/> is left at its default
|
||||
/// (<c>Skip</c>); setting it to <c>Disallow</c> would break backward-
|
||||
/// compatible deserialization of pre-C4 bundles, which may carry a top-level
|
||||
/// compatible deserialization of older bundles, which may carry a top-level
|
||||
/// <c>apiKeys</c> array and/or <c>ApprovedApiKeyIds</c> fields inside
|
||||
/// <c>apiMethods[]</c> entries. That tolerance is load-bearing and must be
|
||||
/// preserved.
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace ZB.MOM.WW.ScadaBridge.Transport.Serialization;
|
||||
/// on the application side of the bundle boundary.
|
||||
/// </summary>
|
||||
// ApiKeys is intentionally absent: inbound API keys are not transported between
|
||||
// environments (re-arch C4). The aggregate only carries API methods.
|
||||
// environments. The aggregate only carries API methods.
|
||||
public sealed record EntityAggregate(
|
||||
IReadOnlyList<TemplateFolder> TemplateFolders,
|
||||
IReadOnlyList<Template> Templates,
|
||||
@@ -28,15 +28,15 @@ public sealed record EntityAggregate(
|
||||
IReadOnlyList<SmtpConfiguration> SmtpConfigurations,
|
||||
IReadOnlyList<ApiMethod> ApiMethods)
|
||||
{
|
||||
// M8: site/instance-scoped entities. Init-only with empty-array defaults so
|
||||
// Site/instance-scoped entities. Init-only with empty-array defaults so
|
||||
// existing positional `new EntityAggregate(...)` callers keep compiling and
|
||||
// never see a null collection; new callers opt in via object-initializer.
|
||||
public IReadOnlyList<Site> Sites { get; init; } = Array.Empty<Site>();
|
||||
public IReadOnlyList<DataConnection> DataConnections { get; init; } = Array.Empty<DataConnection>();
|
||||
public IReadOnlyList<Instance> Instances { get; init; } = Array.Empty<Instance>();
|
||||
|
||||
// SMS (S10): carried alongside SmtpConfigurations. Init-only with an empty
|
||||
// default for the same source-compat reason as the M8 collections above —
|
||||
// SMS: carried alongside SmtpConfigurations. Init-only with an empty
|
||||
// default for the same source-compat reason as the site/instance collections above —
|
||||
// every existing positional `new EntityAggregate(...)` caller keeps compiling
|
||||
// and never sees null; producers that resolve SMS config opt in via
|
||||
// object-initializer.
|
||||
@@ -52,7 +52,7 @@ public sealed record EntityAggregate(
|
||||
/// <para>
|
||||
/// <see cref="ApiKeys"/> is a <b>legacy, read-only</b> field retained purely for
|
||||
/// backward-compatible deserialization of bundles produced before the
|
||||
/// inbound-API-key re-architecture (C4). New exports never populate it (it stays
|
||||
/// inbound-API-key re-architecture. New exports never populate it (it stays
|
||||
/// <c>null</c> and is dropped from the JSON by the serializer's
|
||||
/// <c>WhenWritingNull</c> policy); the importer counts any keys present in an old
|
||||
/// bundle, ignores them, and surfaces a note — keys are re-created per environment.
|
||||
@@ -69,7 +69,7 @@ public sealed record BundleContentDto(
|
||||
IReadOnlyList<ApiMethodDto> ApiMethods,
|
||||
IReadOnlyList<ApiKeyDto>? ApiKeys = null)
|
||||
{
|
||||
// M8: site/instance-scoped payloads. Modeled as init-only properties with
|
||||
// Site/instance-scoped payloads. Modeled as init-only properties with
|
||||
// empty-array defaults (rather than additional positional ctor params) for
|
||||
// two reasons:
|
||||
// 1. Forward-compat: deserializing an OLDER bundle whose content blob has
|
||||
@@ -85,9 +85,9 @@ public sealed record BundleContentDto(
|
||||
public IReadOnlyList<DataConnectionDto> DataConnections { get; init; } = Array.Empty<DataConnectionDto>();
|
||||
public IReadOnlyList<InstanceDto> Instances { get; init; } = Array.Empty<InstanceDto>();
|
||||
|
||||
// SMS (S10): central-only SMS provider configs, carried alongside SmtpConfigs.
|
||||
// SMS: central-only SMS provider configs, carried alongside SmtpConfigs.
|
||||
// Modeled as an init-only property with an empty default (NOT a positional ctor
|
||||
// param) for the same two reasons as the M8 site/instance arrays above:
|
||||
// param) for the same two reasons as the site/instance arrays above:
|
||||
// 1. Forward-compat: deserializing a bundle written before SMS support leaves
|
||||
// this at Array.Empty<SmsConfigDto>() — consumers always see an empty list,
|
||||
// never null.
|
||||
@@ -146,7 +146,7 @@ public sealed record TemplateScriptDto(
|
||||
string? ReturnDefinition,
|
||||
bool IsLocked,
|
||||
TimeSpan? MinTimeBetweenRuns,
|
||||
// M2.5 (#9): per-script execution timeout (seconds). Additive trailing field;
|
||||
// Per-script execution timeout (seconds). Additive trailing field;
|
||||
// null on bundles written before this field existed.
|
||||
int? ExecutionTimeoutSeconds = null);
|
||||
|
||||
@@ -189,12 +189,12 @@ public sealed record NotificationListDto(
|
||||
|
||||
public sealed record NotificationRecipientDto(
|
||||
string Name,
|
||||
// S10: nullable so an SMS-only recipient (no email) round-trips faithfully
|
||||
// Nullable so an SMS-only recipient (no email) round-trips faithfully
|
||||
// instead of being coerced to an empty string. Email-only recipients (the
|
||||
// historical case) still carry a non-null address; the entity enforces that at
|
||||
// least one contact is present.
|
||||
string? EmailAddress,
|
||||
// S10: SMS recipients carry an E.164 phone number instead of (or in addition
|
||||
// SMS recipients carry an E.164 phone number instead of (or in addition
|
||||
// to) an email. Trailing + nullable so a bundle written before SMS support
|
||||
// deserializes this as null (backward-compatible); the serializer's
|
||||
// WhenWritingNull policy keeps it out of email-only bundles' JSON.
|
||||
@@ -228,8 +228,9 @@ public sealed record SmsConfigDto(
|
||||
TimeSpan RetryDelay,
|
||||
SecretsBlock? Secrets);
|
||||
|
||||
// Legacy DTO: only deserialized from pre-C4 bundles so the importer can count and
|
||||
// ignore the keys they contain. New exports never emit an ApiKeys array.
|
||||
// Legacy DTO: only deserialized from bundles produced before the inbound-API-key
|
||||
// re-architecture so the importer can count and ignore the keys they contain.
|
||||
// New exports never emit an ApiKeys array.
|
||||
public sealed record ApiKeyDto(
|
||||
string Name,
|
||||
string KeyHash,
|
||||
@@ -237,7 +238,7 @@ public sealed record ApiKeyDto(
|
||||
SecretsBlock? Secrets);
|
||||
|
||||
// ApprovedApiKeyIds is intentionally absent: it linked methods to keys that are no
|
||||
// longer transported (re-arch C4). Scopes are re-granted per environment. The field
|
||||
// longer transported. Scopes are re-granted per environment. The field
|
||||
// in any old bundle is simply ignored on read.
|
||||
public sealed record ApiMethodDto(
|
||||
string Name,
|
||||
@@ -246,7 +247,7 @@ public sealed record ApiMethodDto(
|
||||
string? ReturnDefinition,
|
||||
int TimeoutSeconds);
|
||||
|
||||
// --- M8: site/instance-scoped transport DTOs --------------------------------
|
||||
// --- Site/instance-scoped transport DTOs --------------------------------
|
||||
// These travel alongside the original central-config DTOs above. Sites and
|
||||
// instances are referenced by their stable string identities (SiteIdentifier,
|
||||
// UniqueName, TemplateName) rather than database ids so a bundle resolves
|
||||
|
||||
@@ -29,7 +29,7 @@ public sealed class EntitySerializer
|
||||
var folderNameById = aggregate.TemplateFolders.ToDictionary(f => f.Id, f => f.Name);
|
||||
var templateNameById = aggregate.Templates.ToDictionary(t => t.Id, t => t.Name);
|
||||
|
||||
// M8 name-link lookups. Instances/data-connections reference their owning
|
||||
// Name-link lookups. Instances/data-connections reference their owning
|
||||
// site by the portable SiteIdentifier (not the EF surrogate SiteId); a
|
||||
// connection binding references its DataConnection by Name. Build both
|
||||
// id→name maps once so the projections below resolve in O(1).
|
||||
@@ -138,7 +138,7 @@ public sealed class EntitySerializer
|
||||
NotificationLists: aggregate.NotificationLists.Select(nl => new NotificationListDto(
|
||||
Name: nl.Name,
|
||||
Type: nl.Type,
|
||||
// S10: carry BOTH contacts. Keep any recipient that has at least
|
||||
// Carry BOTH contacts. Keep any recipient that has at least
|
||||
// one contact (email OR phone) — SMS-only recipients have a null
|
||||
// EmailAddress and would have been dropped by the old email-only
|
||||
// filter. EmailAddress/PhoneNumber are nullable on the DTO so a
|
||||
@@ -172,7 +172,7 @@ public sealed class EntitySerializer
|
||||
RetryDelay: smtp.RetryDelay,
|
||||
Secrets: secrets);
|
||||
}).ToList(),
|
||||
// Inbound API keys are not transported between environments (re-arch C4):
|
||||
// Inbound API keys are not transported between environments:
|
||||
// the bundle carries API methods only. ApiMethod.ApprovedApiKeyIds is also
|
||||
// excluded — it references keys that aren't in the bundle; method→key scopes
|
||||
// are re-granted per environment via the admin UI/CLI. The legacy ApiKeys
|
||||
@@ -184,7 +184,7 @@ public sealed class EntitySerializer
|
||||
ReturnDefinition: m.ReturnDefinition,
|
||||
TimeoutSeconds: m.TimeoutSeconds)).ToList())
|
||||
{
|
||||
// M8 site/instance-scoped payloads. These are init-only (non-positional)
|
||||
// Site/instance-scoped payloads. These are init-only (non-positional)
|
||||
// on BundleContentDto, so they're set via object-initializer here.
|
||||
Sites = aggregate.Sites.Select(s => new SiteDto(
|
||||
SiteIdentifier: s.SiteIdentifier,
|
||||
@@ -218,7 +218,7 @@ public sealed class EntitySerializer
|
||||
FailoverRetryCount: c.FailoverRetryCount,
|
||||
Secrets: secretValues.Count > 0 ? new SecretsBlock(secretValues) : null);
|
||||
}).ToList(),
|
||||
// SMS (S10): mirror the SMTP secret handling exactly — the provider
|
||||
// SMS: mirror the SMTP secret handling exactly — the provider
|
||||
// auth token (never a public field) rides inside the SecretsBlock, so a
|
||||
// "share without secrets" export can drop it as a unit. Omit the secret
|
||||
// entirely when the token is null/empty so the importer's TryGetValue
|
||||
@@ -248,7 +248,7 @@ public sealed class EntitySerializer
|
||||
UniqueName: inst.UniqueName,
|
||||
TemplateName: templateNameById.TryGetValue(inst.TemplateId, out var tn) ? tn : string.Empty,
|
||||
SiteIdentifier: siteIdentifierBySiteId.TryGetValue(inst.SiteId, out var isid) ? isid : string.Empty,
|
||||
// TODO(M8): Areas don't travel in the bundle yet — EntityAggregate
|
||||
// TODO: Areas don't travel in the bundle yet — EntityAggregate
|
||||
// carries no Areas collection, so there's no id→name lookup. Emit
|
||||
// null until area transport is added; the importer leaves AreaId null.
|
||||
AreaName: null,
|
||||
@@ -268,7 +268,7 @@ public sealed class EntitySerializer
|
||||
ConditionFilterOverride: o.ConditionFilterOverride)).ToList(),
|
||||
// Connection bindings reference their DataConnection by NAME — the
|
||||
// numeric DataConnectionId FK can't survive a cross-environment
|
||||
// bundle, so the importer (D1) resolves ConnectionName→target FK at
|
||||
// bundle, so the importer resolves ConnectionName→target FK at
|
||||
// apply time. If the FK doesn't resolve in this aggregate (orphan
|
||||
// row), the name comes through empty.
|
||||
ConnectionBindings: inst.ConnectionBindings.Select(b => new InstanceConnectionBindingDto(
|
||||
@@ -424,7 +424,7 @@ public sealed class EntitySerializer
|
||||
var list = new NotificationList(dto.Name) { Id = ix + 1, Type = dto.Type };
|
||||
foreach (var r in dto.Recipients)
|
||||
{
|
||||
// S10: reconstruct whichever contact(s) the bundle carries.
|
||||
// Reconstruct whichever contact(s) the bundle carries.
|
||||
// Email-present recipients use the email ctor (unchanged
|
||||
// historical path) and additively restore the phone number;
|
||||
// phone-only recipients (null email) take the SMS factory so we
|
||||
@@ -453,7 +453,7 @@ public sealed class EntitySerializer
|
||||
})
|
||||
.ToList();
|
||||
|
||||
// SMS (S10): mirror the SMTP path — restore AccountSid/FromNumber and decrypt
|
||||
// SMS: mirror the SMTP path — restore AccountSid/FromNumber and decrypt
|
||||
// the auth token back out of the SecretsBlock (null when the key was omitted
|
||||
// because the source token was null/empty).
|
||||
var smsConfigurations = content.SmsConfigs
|
||||
@@ -469,7 +469,7 @@ public sealed class EntitySerializer
|
||||
})
|
||||
.ToList();
|
||||
|
||||
// Inbound API keys are not transported (re-arch C4) — content.ApiKeys is a
|
||||
// Inbound API keys are not transported — content.ApiKeys is a
|
||||
// legacy field only present on pre-C4 bundles; it is ignored here. The
|
||||
// BundleImporter is responsible for counting and reporting any such keys.
|
||||
// ApiMethod.ApprovedApiKeyIds is likewise not reconstructed: scopes are
|
||||
@@ -484,7 +484,7 @@ public sealed class EntitySerializer
|
||||
})
|
||||
.ToList();
|
||||
|
||||
// M8: sites first — assign synthetic ids by ordinal. Addresses are carried
|
||||
// Sites first — assign synthetic ids by ordinal. Addresses are carried
|
||||
// verbatim; the importer decides whether to keep or rewrite them.
|
||||
var sites = content.Sites
|
||||
.Select((dto, ix) => new Site(dto.Name, dto.SiteIdentifier)
|
||||
@@ -516,7 +516,7 @@ public sealed class EntitySerializer
|
||||
|
||||
// Instances: resolve template + site by name/identifier. Areas don't travel
|
||||
// (see export TODO), so AreaId stays null. Connection bindings keep their
|
||||
// resolved DataConnection NAME on the wire DTO — the importer (D1) reads
|
||||
// resolved DataConnection NAME on the wire DTO — the importer reads
|
||||
// bindings from BundleContentDto.Instances[].ConnectionBindings directly and
|
||||
// resolves ConnectionName→the target environment's DataConnectionId at apply
|
||||
// time. FromBundleContent is NOT on the importer's path (BundleImporter walks
|
||||
|
||||
@@ -13,7 +13,7 @@ public sealed class ManifestBuilder
|
||||
{
|
||||
public const int CurrentBundleFormatVersion = 1;
|
||||
|
||||
// Schema minor version. Bumped 1.0 → 1.1 in M8 to carry the additive
|
||||
// Schema minor version. Bumped 1.0 → 1.1 to carry the additive
|
||||
// site/dataConnection/instance summary counts (and their content arrays).
|
||||
// Minor bumps are additive-only: ManifestValidator gates solely on
|
||||
// BundleFormatVersion, so an older "1.0" bundle still validates Ok.
|
||||
|
||||
Reference in New Issue
Block a user