|
| 1 | +# RegiLattice — Plugin Marketplace Design |
| 2 | + |
| 3 | +> **Status**: Plan only — not yet implemented. |
| 4 | +> **Target**: v4.0.0+ |
| 5 | +> **Author**: RajwanYair |
| 6 | +> **Created**: 2025-07-21 |
| 7 | +
|
| 8 | +--- |
| 9 | + |
| 10 | +## Goals |
| 11 | + |
| 12 | +1. Allow users to install community-authored **Tweak Packs** without recompiling |
| 13 | +2. Allow publishing Tweak Packs to a central GitHub-hosted index |
| 14 | +3. Keep the security model tight — no arbitrary code execution from untrusted sources |
| 15 | +4. Minimal impact on the existing codebase (additive, not refactoring) |
| 16 | + |
| 17 | +--- |
| 18 | + |
| 19 | +## Architecture Overview |
| 20 | + |
| 21 | +``` |
| 22 | +┌────────────────────────────────────────────────────┐ |
| 23 | +│ RegiLattice GUI / CLI │ |
| 24 | +│ │ |
| 25 | +│ ┌─────────────┐ ┌───────────┐ ┌────────────┐ │ |
| 26 | +│ │ TweakEngine │◄──│ PluginMgr │──►│ IndexCache │ │ |
| 27 | +│ │ (built-in) │ │ │ │ (local) │ │ |
| 28 | +│ └─────────────┘ └─────┬─────┘ └────────────┘ │ |
| 29 | +│ │ │ |
| 30 | +└───────────────────────────┼─────────────────────────┘ |
| 31 | + │ HTTPS (read-only) |
| 32 | + ▼ |
| 33 | + ┌──────────────────────────┐ |
| 34 | + │ GitHub Repository Index │ |
| 35 | + │ RajwanYair/regilattice- │ |
| 36 | + │ marketplace │ |
| 37 | + │ ├── index.json │ |
| 38 | + │ └── packs/ │ |
| 39 | + │ ├── gaming-extra/ │ |
| 40 | + │ ├── developer/ │ |
| 41 | + │ └── privacy-pro/ │ |
| 42 | + └──────────────────────────┘ |
| 43 | +``` |
| 44 | + |
| 45 | +### Key Design Decisions |
| 46 | + |
| 47 | +| Decision | Choice | Rationale | |
| 48 | +|----------|--------|-----------| |
| 49 | +| Pack format | JSON (declarative TweakDefs) | No .dll loading = no code execution risk | |
| 50 | +| Distribution | GitHub repo + raw.githubusercontent | Free, versioned, no server infrastructure | |
| 51 | +| Index | Single `index.json` at repo root | Simple, cacheable, no database needed | |
| 52 | +| Install location | `%LOCALAPPDATA%\RegiLattice\packs\` | User-scoped, no admin for install | |
| 53 | +| Verification | SHA-256 hash in index | Integrity check, not full signing (v1) | |
| 54 | + |
| 55 | +--- |
| 56 | + |
| 57 | +## Tweak Pack Format |
| 58 | + |
| 59 | +A Tweak Pack is a single `.json` file containing an array of declarative tweak definitions. |
| 60 | +Only the **declarative RegOp pattern** is supported — no custom `ApplyAction` / `DetectAction`. |
| 61 | + |
| 62 | +### `pack.json` Schema |
| 63 | + |
| 64 | +```json |
| 65 | +{ |
| 66 | + "name": "gaming-extra", |
| 67 | + "displayName": "Gaming Extra Tweaks", |
| 68 | + "version": "1.0.0", |
| 69 | + "author": "RajwanYair", |
| 70 | + "description": "25 additional gaming performance tweaks for competitive FPS players.", |
| 71 | + "minRegiLatticeVersion": "3.1.0", |
| 72 | + "minWindowsBuild": 22621, |
| 73 | + "categories": ["Gaming Extra"], |
| 74 | + "tags": ["gaming", "fps", "performance", "latency"], |
| 75 | + "tweaks": [ |
| 76 | + { |
| 77 | + "id": "gx-disable-game-bar-recording", |
| 78 | + "label": "Disable Game Bar Recording", |
| 79 | + "category": "Gaming Extra", |
| 80 | + "description": "Prevents Game Bar from auto-recording gameplay clips.", |
| 81 | + "tags": ["gaming", "performance"], |
| 82 | + "needsAdmin": true, |
| 83 | + "corpSafe": false, |
| 84 | + "minBuild": 22621, |
| 85 | + "applyOps": [ |
| 86 | + { "kind": "SetDword", "path": "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\GameBar", "name": "AutoGameModeEnabled", "dwordValue": 0 } |
| 87 | + ], |
| 88 | + "removeOps": [ |
| 89 | + { "kind": "DeleteValue", "path": "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\GameBar", "name": "AutoGameModeEnabled" } |
| 90 | + ], |
| 91 | + "detectOps": [ |
| 92 | + { "kind": "CheckDword", "path": "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\GameBar", "name": "AutoGameModeEnabled", "dwordValue": 0 } |
| 93 | + ] |
| 94 | + } |
| 95 | + ] |
| 96 | +} |
| 97 | +``` |
| 98 | + |
| 99 | +### Supported RegOp Kinds in JSON |
| 100 | + |
| 101 | +| Kind | Required Fields | |
| 102 | +|------|-----------------| |
| 103 | +| `SetDword` | `path`, `name`, `dwordValue` | |
| 104 | +| `SetString` | `path`, `name`, `stringValue` | |
| 105 | +| `SetExpandString` | `path`, `name`, `stringValue` | |
| 106 | +| `SetQword` | `path`, `name`, `qwordValue` | |
| 107 | +| `SetBinary` | `path`, `name`, `binaryValue` (base64) | |
| 108 | +| `SetMultiSz` | `path`, `name`, `multiSzValue` (string[]) | |
| 109 | +| `DeleteValue` | `path`, `name` | |
| 110 | +| `DeleteTree` | `path` | |
| 111 | +| `CheckDword` | `path`, `name`, `dwordValue` | |
| 112 | +| `CheckString` | `path`, `name`, `stringValue` | |
| 113 | +| `CheckMissing` | `path`, `name` | |
| 114 | +| `CheckKeyMissing` | `path` | |
| 115 | + |
| 116 | +--- |
| 117 | + |
| 118 | +## Index Repository Structure |
| 119 | + |
| 120 | +``` |
| 121 | +RajwanYair/regilattice-marketplace/ |
| 122 | +├── index.json # Master index of all packs |
| 123 | +├── README.md # Community guidelines |
| 124 | +├── CONTRIBUTING.md # How to submit a pack |
| 125 | +├── schema/ |
| 126 | +│ ├── pack.schema.json # JSON Schema for pack validation |
| 127 | +│ └── index.schema.json # JSON Schema for index |
| 128 | +└── packs/ |
| 129 | + ├── gaming-extra/ |
| 130 | + │ ├── pack.json # The pack definition |
| 131 | + │ └── README.md # Pack documentation |
| 132 | + ├── developer/ |
| 133 | + │ ├── pack.json |
| 134 | + │ └── README.md |
| 135 | + └── privacy-pro/ |
| 136 | + ├── pack.json |
| 137 | + └── README.md |
| 138 | +``` |
| 139 | + |
| 140 | +### `index.json` Schema |
| 141 | + |
| 142 | +```json |
| 143 | +{ |
| 144 | + "version": 1, |
| 145 | + "lastUpdated": "2025-07-21T00:00:00Z", |
| 146 | + "packs": [ |
| 147 | + { |
| 148 | + "name": "gaming-extra", |
| 149 | + "displayName": "Gaming Extra Tweaks", |
| 150 | + "version": "1.0.0", |
| 151 | + "author": "RajwanYair", |
| 152 | + "description": "25 additional gaming performance tweaks.", |
| 153 | + "tweakCount": 25, |
| 154 | + "categories": ["Gaming Extra"], |
| 155 | + "tags": ["gaming", "fps"], |
| 156 | + "sha256": "abc123...", |
| 157 | + "downloadUrl": "https://raw.githubusercontent.com/RajwanYair/regilattice-marketplace/main/packs/gaming-extra/pack.json", |
| 158 | + "minRegiLatticeVersion": "3.1.0" |
| 159 | + } |
| 160 | + ] |
| 161 | +} |
| 162 | +``` |
| 163 | + |
| 164 | +--- |
| 165 | + |
| 166 | +## Implementation Plan |
| 167 | + |
| 168 | +### Phase 1 — Core Plugin Infrastructure (`RegiLattice.Core`) |
| 169 | + |
| 170 | +**New files:** |
| 171 | + |
| 172 | +| File | Purpose | |
| 173 | +|------|---------| |
| 174 | +| `src/RegiLattice.Core/Plugins/PackDef.cs` | Pack metadata model (sealed record) | |
| 175 | +| `src/RegiLattice.Core/Plugins/PackLoader.cs` | JSON → TweakDef[] deserialiser + validator | |
| 176 | +| `src/RegiLattice.Core/Plugins/PackIndex.cs` | Index model + fetch from GitHub | |
| 177 | +| `src/RegiLattice.Core/Plugins/PackManager.cs` | Install / uninstall / list / update packs | |
| 178 | + |
| 179 | +**Changes to existing:** |
| 180 | + |
| 181 | +| File | Change | |
| 182 | +|------|--------| |
| 183 | +| `TweakEngine.cs` | Add `RegisterPack(PackDef)` method | |
| 184 | +| `TweakDef.cs` | Add `PackSource` property (null = built-in) | |
| 185 | + |
| 186 | +**Key classes:** |
| 187 | + |
| 188 | +```csharp |
| 189 | +// Models |
| 190 | +public sealed record PackDef( |
| 191 | + string Name, |
| 192 | + string DisplayName, |
| 193 | + string Version, |
| 194 | + string Author, |
| 195 | + string Description, |
| 196 | + int TweakCount, |
| 197 | + IReadOnlyList<string> Categories, |
| 198 | + IReadOnlyList<string> Tags, |
| 199 | + string Sha256, |
| 200 | + string DownloadUrl, |
| 201 | + string MinRegiLatticeVersion); |
| 202 | + |
| 203 | +public sealed record PackIndex( |
| 204 | + int Version, |
| 205 | + DateTime LastUpdated, |
| 206 | + IReadOnlyList<PackDef> Packs); |
| 207 | + |
| 208 | +// Core manager |
| 209 | +public sealed class PackManager |
| 210 | +{ |
| 211 | + private readonly string _packsDir; // %LOCALAPPDATA%\RegiLattice\packs\ |
| 212 | +
|
| 213 | + public IReadOnlyList<PackDef> InstalledPacks(); |
| 214 | + public async Task<PackIndex> FetchIndexAsync(CancellationToken ct); |
| 215 | + public async Task<IReadOnlyList<TweakDef>> InstallPackAsync(string name, CancellationToken ct); |
| 216 | + public bool UninstallPack(string name); |
| 217 | + public async Task<IReadOnlyList<TweakDef>> UpdatePackAsync(string name, CancellationToken ct); |
| 218 | +} |
| 219 | + |
| 220 | +// Loader |
| 221 | +public static class PackLoader |
| 222 | +{ |
| 223 | + public static IReadOnlyList<TweakDef> LoadFromJson(string json, string packName); |
| 224 | + public static bool ValidatePackJson(string json, out IReadOnlyList<string> errors); |
| 225 | +} |
| 226 | +``` |
| 227 | + |
| 228 | +### Phase 2 — CLI Integration |
| 229 | + |
| 230 | +**New CLI commands:** |
| 231 | + |
| 232 | +| Command | Description | |
| 233 | +|---------|-------------| |
| 234 | +| `--marketplace list` | Show available packs from index | |
| 235 | +| `--marketplace search <query>` | Search packs by name/tag | |
| 236 | +| `--marketplace install <name>` | Download and install a pack | |
| 237 | +| `--marketplace update <name>` | Update an installed pack | |
| 238 | +| `--marketplace uninstall <name>` | Remove an installed pack | |
| 239 | +| `--marketplace installed` | List locally installed packs | |
| 240 | +| `--marketplace info <name>` | Show pack details | |
| 241 | + |
| 242 | +### Phase 3 — GUI Integration |
| 243 | + |
| 244 | +**New UI elements:** |
| 245 | + |
| 246 | +| Element | Location | Description | |
| 247 | +|---------|----------|-------------| |
| 248 | +| Marketplace tab | Main sidebar | Browse/search/install packs | |
| 249 | +| Pack detail panel | Marketplace tab | Name, author, version, tweak count, install button | |
| 250 | +| Installed badge | Category tree | Show (plugin) badge next to pack categories | |
| 251 | +| Update indicator | Status bar | "2 pack updates available" notification | |
| 252 | + |
| 253 | +**New dialog: `MarketplaceDialog.cs`** |
| 254 | + |
| 255 | +- Tabbed: Browse | Installed | Updates |
| 256 | +- Browse: search bar + pack cards (name, author, stars, install button) |
| 257 | +- Installed: list with uninstall/update buttons |
| 258 | +- Updates: one-click "Update All" |
| 259 | + |
| 260 | +### Phase 4 — Community & Governance |
| 261 | + |
| 262 | +| Task | Description | |
| 263 | +|------|-------------| |
| 264 | +| JSON Schema validation | CI action validates all pack.json against schema | |
| 265 | +| SHA-256 integrity | Client verifies hash before loading any pack | |
| 266 | +| Author verification | GitHub account linked, display verified badge | |
| 267 | +| Review process | PR-based submission, manual review before merge to index | |
| 268 | +| Guidelines | Max 100 tweaks per pack, no HKLM writes without justification | |
| 269 | +| Reporting | Flag mechanism for malicious packs | |
| 270 | + |
| 271 | +--- |
| 272 | + |
| 273 | +## Security Model |
| 274 | + |
| 275 | +### Threat vectors & mitigations |
| 276 | + |
| 277 | +| Threat | Mitigation | |
| 278 | +|--------|------------| |
| 279 | +| Malicious registry writes | JSON-only — no .dll execution, no Process.Start | |
| 280 | +| Pack tampering in transit | SHA-256 hash verification from index | |
| 281 | +| Path traversal in registry paths | Validate all paths start with `HKEY_` prefix | |
| 282 | +| Denial of service (huge pack) | Max 100 tweaks per pack, max 1MB file size | |
| 283 | +| Index poisoning | HTTPS-only fetch, pinned to specific GitHub repo | |
| 284 | +| Stale/broken tweaks | `DetectOps` required for all pack tweaks | |
| 285 | + |
| 286 | +### Validation rules for pack tweaks |
| 287 | + |
| 288 | +1. All IDs must be prefixed with pack name: `{pack}-{tweak-name}` |
| 289 | +2. All registry paths must start with `HKEY_CURRENT_USER\` or `HKEY_LOCAL_MACHINE\` |
| 290 | +3. `ApplyOps`, `RemoveOps`, and `DetectOps` must all be non-empty |
| 291 | +4. No duplicate IDs (checked against built-in + all installed packs) |
| 292 | +5. `Category` must match declared pack categories |
| 293 | +6. `minBuild` must be reasonable (>= 19041 for Win10 2004+) |
| 294 | + |
| 295 | +--- |
| 296 | + |
| 297 | +## File Layout After Implementation |
| 298 | + |
| 299 | +``` |
| 300 | +src/RegiLattice.Core/ |
| 301 | +├── Plugins/ |
| 302 | +│ ├── PackDef.cs # Pack metadata record |
| 303 | +│ ├── PackIndex.cs # Index model + deserialisation |
| 304 | +│ ├── PackLoader.cs # JSON → TweakDef[] + validation |
| 305 | +│ └── PackManager.cs # Install/uninstall/update/list |
| 306 | +tests/RegiLattice.Core.Tests/ |
| 307 | +├── PackLoaderTests.cs # Pack JSON parsing, validation, edge cases |
| 308 | +├── PackManagerTests.cs # Install/uninstall with temp dir |
| 309 | +``` |
| 310 | + |
| 311 | +--- |
| 312 | + |
| 313 | +## Estimated Effort |
| 314 | + |
| 315 | +| Phase | Effort | Dependencies | |
| 316 | +|-------|--------|--------------| |
| 317 | +| Phase 1 — Core infrastructure | 2-3 sessions | None | |
| 318 | +| Phase 2 — CLI commands | 1 session | Phase 1 | |
| 319 | +| Phase 3 — GUI dialog | 2 sessions | Phase 1 | |
| 320 | +| Phase 4 — Community repo | 1 session | Phase 1 | |
| 321 | +| **Total** | **6-7 sessions** | | |
| 322 | + |
| 323 | +--- |
| 324 | + |
| 325 | +## Open Questions |
| 326 | + |
| 327 | +1. **Versioning**: Should packs follow semver independently, or track RegiLattice version? |
| 328 | + - **Recommendation**: Independent semver with `minRegiLatticeVersion` constraint. |
| 329 | + |
| 330 | +2. **Custom categories**: Can packs create new categories, or only add to existing? |
| 331 | + - **Recommendation**: Packs can create new categories (prefixed with pack name). |
| 332 | + |
| 333 | +3. **Offline mode**: Should packs work fully offline once installed? |
| 334 | + - **Recommendation**: Yes — installed packs are fully self-contained JSON. |
| 335 | + |
| 336 | +4. **Rating system**: Should packs have a rating/review system? |
| 337 | + - **Recommendation**: Defer to v4.1. Start with download count only. |
| 338 | + |
| 339 | +5. **Auto-update**: Should packs auto-update, or require manual action? |
| 340 | + - **Recommendation**: Notify only. User must explicitly update. |
0 commit comments