server-monitor-manager/agents/_salvage-2026-08-18/panel-control/Task3-B3-2026-08-04/trimmed-orphan-verifier/Program.cs
Ochenstarik 23eb3f5233 chore(agents): разбор рабочих папок с диска на 2026-08-18
Задания, отчёты и патчи, лежавшие в C:\Users\Ochenstarik\projects и в
домашней папке, перенесены в agents/. Разложено по агентам там, где имя
файла позволяло определить автора; остальное — в _salvage-2026-08-18/
и разбирается вручную.

Патчи в notes/salvage-2026-08-18/ — незакоммиченная работа из брошенных
рабочих копий: она существовала только на диске.

Тяжёлое (релизные архивы, инсталляторы, наборы данных) в репозиторий не
попало: оно лежит рядом, в Agent_projects/_archive и Agent_projects/_data.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 14:19:54 +07:00

118 lines
4.8 KiB
C#

using System.Text.Json;
using System.Security.Cryptography;
using Microsoft.Data.Sqlite;
using Microsoft.Extensions.Options;
using ServerMonitorManager.Control;
using ServerMonitorManager.Core;
var root = Path.Combine(Path.GetTempPath(), $"smm-trimmed-orphan-{Guid.NewGuid():N}");
Directory.CreateDirectory(root);
var databasePath = Path.Combine(root, "control.db");
try
{
var loadedControlAssembly = typeof(ControlStore).Assembly.Location;
var loadedControlSha256 = Convert.ToHexString(
SHA256.HashData(await File.ReadAllBytesAsync(loadedControlAssembly))).ToLowerInvariant();
var store = new ControlStore(Options.Create(new ControlOptions
{
DatabasePath = databasePath,
CertificateAuthorityPath = Path.Combine(root, "unused.pfx")
}));
await store.InitializeAsync();
var orphan = new LinkRule("source", "target", "tcp", 2222);
var applier = new OrphanApplier(orphan);
var service = new LinkService(store, applier, new ControlEventBroker());
var result = await service.ReconcileAllAsync();
Require(result.Examined == 1, $"Examined={result.Examined}");
Require(result.Converged == 1, $"Converged={result.Converged}");
Require(result.Failed == 0, $"Failed={result.Failed}");
Require(result.Deferred == 0, $"Deferred={result.Deferred}");
Require(applier.ListCalls == 2, $"ListCalls={applier.ListCalls}");
Require(applier.RawDisconnectCalls == 1, $"RawDisconnectCalls={applier.RawDisconnectCalls}");
await using var connection = new SqliteConnection($"Data Source={databasePath}");
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = """
SELECT actor, action, subject, details_json
FROM audit
WHERE action = 'link.orphan-removed'
ORDER BY sequence;
""";
await using var reader = await command.ExecuteReaderAsync();
Require(await reader.ReadAsync(), "orphan audit row missing");
var actor = reader.GetString(0);
var action = reader.GetString(1);
var subject = reader.GetString(2);
var detailsJson = reader.GetString(3);
Require(!await reader.ReadAsync(), "duplicate orphan audit rows");
Require(actor == "system:reconcile", $"actor={actor}");
Require(action == "link.orphan-removed", $"action={action}");
Require(subject == "source:target:tcp:2222", $"subject={subject}");
using var details = JsonDocument.Parse(detailsJson);
var rootElement = details.RootElement;
Require(rootElement.GetProperty("sourceNodeId").GetString() == "source", detailsJson);
Require(rootElement.GetProperty("targetNodeId").GetString() == "target", detailsJson);
Require(rootElement.GetProperty("protocol").GetString() == "tcp", detailsJson);
Require(rootElement.GetProperty("port").GetInt32() == 2222, detailsJson);
Require(rootElement.EnumerateObject().Count() == 4, detailsJson);
Console.WriteLine("TRIMMED_ORPHAN_AUDIT=PASS");
Console.WriteLine($"LOADED_CONTROL_ASSEMBLY={loadedControlAssembly}");
Console.WriteLine($"LOADED_CONTROL_SHA256={loadedControlSha256}");
Console.WriteLine($"RESULT={result.Examined}/{result.Converged}/{result.Failed}/{result.Deferred}");
Console.WriteLine($"HELPER_CALLS=list:{applier.ListCalls},raw-disconnect:{applier.RawDisconnectCalls}");
Console.WriteLine($"AUDIT={actor}|{action}|{subject}|{detailsJson}");
}
finally
{
SqliteConnection.ClearAllPools();
if (Directory.Exists(root))
{
Directory.Delete(root, recursive: true);
}
}
static void Require(bool condition, string message)
{
if (!condition)
{
throw new InvalidOperationException(message);
}
}
sealed class OrphanApplier(LinkRule orphan) : ILinkPolicyApplier
{
private bool _connected = true;
public int ListCalls { get; private set; }
public int RawDisconnectCalls { get; private set; }
public Task<IReadOnlyList<LinkRule>> ListRulesAsync(CancellationToken cancellationToken)
{
ListCalls++;
return Task.FromResult<IReadOnlyList<LinkRule>>(_connected ? [orphan] : []);
}
public Task ApplyConnectAsync(LinkPolicy link, CancellationToken cancellationToken)
=> throw new InvalidOperationException("Unexpected connect.");
public Task ApplyDisconnectAsync(LinkPolicy link, CancellationToken cancellationToken)
=> throw new InvalidOperationException("Unexpected persisted disconnect.");
public Task ApplyDisconnectAsync(LinkRule rule, CancellationToken cancellationToken)
{
if (rule != orphan)
{
throw new InvalidOperationException($"Unexpected raw rule: {rule}");
}
RawDisconnectCalls++;
_connected = false;
return Task.CompletedTask;
}
public Task<bool> IsConnectedAsync(LinkPolicy link, CancellationToken cancellationToken)
=> throw new InvalidOperationException("link-status must not be used.");
}