From 1849113fe81138fa77d7883b665404da39f3a882 Mon Sep 17 00:00:00 2001 From: jessikitty Date: Wed, 23 Sep 2026 23:21:49 +1000 Subject: [PATCH] Add architecture doc with build constraints, manifest format, and known issues --- .claude-context/01-architecture.md | 46 ++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 .claude-context/01-architecture.md diff --git a/.claude-context/01-architecture.md b/.claude-context/01-architecture.md new file mode 100644 index 0000000..8813832 --- /dev/null +++ b/.claude-context/01-architecture.md @@ -0,0 +1,46 @@ +# Disco AD Compare Plugin — Architecture + +## Build Environment Constraints +- **MSBuild**: `C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe` (v4.0 only) +- **C# version**: 5 — no interpolation, no `?.`, no auto-property init, no expression-bodied members +- **Target framework**: .NET 4.5 +- **csproj ToolsVersion**: 4.0 +- **No Visual Studio installed on build server** + +## Assembly Reference Strategy +All references resolve from a single directory (`DiscoBinPath`, typically `C:\Program Files\Disco\WebApp\bin`). The build script uses a regex to rewrite all `` entries: +``` +[^<]+\\([^\\<]+\.dll) → $DiscoBinPath\$1 +``` + +## Plugin Packaging +1. Compile with MSBuild → `bin\Release\Disco.Plugins.ADCompare.dll` +2. Generate `manifest.json` (manual, no ManifestGenerator available) +3. Package DLL + PDB + manifest into `.zip`, rename to `.discoPlugin` +4. Import via Disco UI: Configuration → Plugins → Install Plugin + +## Manifest Format +Must match `PluginManifest.cs` / `PluginFeatureManifest.cs` exactly: +- Top level: `Id`, `Name`, `Author`, `Url`, `Version`, `AssemblyPath`, `TypeName`, `ConfigurationHandlerTypeName`, `WebHandlerTypeName`, `Features[]` +- Each feature: `Id`, `Name`, `TypeName`, `PrimaryFeature` (bool), `CategoryTypeName` (string) +- UIExtension category: `Disco.Services.Plugins.Features.UIExtension.UIExtensionFeature``1` + +## AD Comparison Logic +- `managedBy` returns a Distinguished Name (e.g. `CN=Sue Lesnjak,OU=Teachers,...`) +- Disco stores assigned users as `DOMAIN\username` (e.g. `CURRIC\09269037`) +- Comparison requires looking up the assigned user in AD to get their DN, then comparing DN-to-DN +- Devices without `DOMAIN\ComputerName` format (no backslash) are skipped to avoid API errors + +## Plugin Installation Paths +- Installed: `C:\Disco\Plugins\Disco.Plugins.ADCompare\` +- Packages: `C:\Disco\PluginPackages\` +- Storage: `C:\Disco\PluginStorage\` + +## Web Handler Routing +- Route pattern: `Plugin/{PluginId}/{PluginAction}` — action segment is **required** +- Dashboard: `/Plugin/Disco.Plugins.ADCompare/Run` +- Export: `/Plugin/Disco.Plugins.ADCompare/Export` +- Landing: `/Plugin/Disco.Plugins.ADCompare/Index` + +## UIExtension Rendering (UNRESOLVED) +Features initialize successfully (confirmed in Disco logs). Manifest format matches working plugins. `Register()` is called in `Initialize()` override. However, panels don't render on device/user pages. Investigation needed — likely related to how `ExecuteAction` returns are consumed by Disco's Razor views, or possibly a model binding issue with `DeviceShowModel`/`UserShowModel`.