# Technical documentation — magusEvents

Evidence date: 2026-10-09. Inspected revision: `master` at `bb6e583` (2019-08-16).

Source: `git@bitbucket.org:overdrive/magusevents.git`. 40 tracked files. One branch, `master`.

## Repository layout

```text
magusevents/
├── .gitattributes
├── .gitignore
├── MagusEvents.sln                      Visual Studio 2017 (15.0)
└── MagusEvents/
    ├── MagusEvents.sln                  second copy of the solution file
    ├── MagusEvents.csproj               WPF, net46, WinExe
    ├── App.xaml / App.xaml.cs
    ├── App.config
    ├── MainWindow.xaml / .cs
    ├── header.xaml / .cs
    ├── Setup.xaml / .cs
    ├── Scan.xaml / .cs
    ├── Scanmeal.xaml / .cs
    ├── packages.config
    ├── NFC-Logo-1(1).ico
    ├── classes/
    │   ├── Database.cs
    │   ├── Webservices.cs
    │   ├── Person.cs
    │   ├── Events.cs
    │   ├── Zones.cs
    │   ├── Meals.cs
    │   └── Checkin.cs
    ├── images/                          Logo, backgrounds, ok.wav, Bazz.wav
    └── Properties/                      AssemblyInfo, Resources, Settings
```

The onboarding snapshot also named `sonar-project.properties` and `sonarqube_scan.bat` at the scan-host root. They are not tracked at `bb6e583`.

`Build App/` (ClickOnce version `1.0.0.12`, including `setup.exe` and a deployed `NFCSharp.dll`) was tracked in `43bc412` and removed in `bb6e583`.

## Platform

| Item | Value | Evidence |
|---|---|---|
| UI | WPF | `ProjectTypeGuids` includes the WPF GUID; `OutputType` is `WinExe` |
| Framework | .NET Framework 4.6 | `TargetFrameworkVersion`, `App.config` `supportedRuntime` |
| IDE recorded in the sln | Visual Studio 15.0.27130.2003 | `MagusEvents.sln` |
| Assembly | Title and product `MagusEvents`, version `1.0.0.0`, copyright 2019, `ComVisible(false)` | `Properties\AssemblyInfo.cs` |
| Window | `WindowStyle="None"`, `WindowState="Maximized"`, 1920×1080 design surface inside a `Viewbox` | `MainWindow.xaml` |
| Startup | `StartupUri="MainWindow.xaml"` | `App.xaml` |
| Icon | `NFC-Logo-1(1).ico` | csproj `ApplicationIcon` |

`App.config` registers Entity Framework 6 with `LocalDbConnectionFactory` parameter `mssqllocaldb`, plus SQL Server and SQLite EF6 providers. No class in the project subclasses `DbContext` or opens that LocalDB. The running store is SQLite through `System.Data.SQLite`.

## NuGet packages

From `packages.config`. The `packages\` directory is gitignored. The csproj fails the `EnsureNuGetPackageBuildImports` target when `packages\System.Data.SQLite.Core.1.0.109.2\build\net46\System.Data.SQLite.Core.targets` is missing.

| Package | Version |
|---|---|
| EntityFramework | 6.2.0 |
| NAudio | 1.8.5 |
| Newtonsoft.Json | 12.0.1 |
| System.Data.SQLite | 1.0.109.2 |
| System.Data.SQLite.Core | 1.0.109.2 |
| System.Data.SQLite.EF6 | 1.0.109.0 |
| System.Data.SQLite.Linq | 1.0.109.0 |

`Microsoft.VisualBasic` is a framework reference, used for `TextFieldParser`.

`NFCSharp` is not a NuGet package. Hint path:

```text
..\..\..\..\NFC\trunk\TestApp\bin\Debug\NFCSharp.dll
```

That path is outside this repository. A clean clone does not contain the DLL. The first stable commit's ClickOnce folder did contain `NFCSharp.dll.deploy`. That folder is gone at tip.

The csproj also lists content files `x64\SQLite.Interop.dll`, `x86\SQLite.Interop.dll`, and Newtonsoft copies under `x64\` and `x86\`. `.gitignore` ignores `x64/` and `x86/`. They are not tracked.

## Local storage

`Database` opens `Data Source=c:\temp_acc\database.sqlite3`. The directory is created if missing. The file is created with `SQLiteConnection.CreateFile` only when it does not exist, then these tables are created in order: `Events`, `Zones`, `Persons`, `Food`.

No later migration exists. A file created by an older build is opened as-is.

Other files under `c:\temp_acc\`:

| File | Writer | Purpose |
|---|---|---|
| `scan.txt` | `Scan.UserProfile`; created empty by `header` | Zone grant/deny log |
| `meal.txt` | `Scanmeal.ViewProfile`; created empty by `header` | Meal log |
| `LastUpdate.txt` | `Webservices.CheckUpdates` | Timestamp sent as `/date/` on the applicant-update URL |
| `{AAID}.txt` | image download | Profile image payload |
| `accreditations.csv` | not written by the app | Optional import input |
| `Data.json` | path is assigned in `Setup.DownloadStringCompleted` and `Webservices` and then not written | Dead local variable |

`ExecuteData` opens the connection, runs `ExecuteNonQuery`, closes it, and returns whether the affected-row count is greater than 0. Exceptions return false. The connection field is a public instance member. Each call constructs a new `Database`, so connections are not shared, but a swallowed constructor failure leaves `myConnection` null and the next call throws inside a catch that also returns false or an empty object.

SQL text is concatenated. Scanned barcodes, JSON fields, and CSV fields are interpolated inside quotes. There is no parameter API.

### Tables

`Events`: `AC` unique, `AccreditationName`, `DateFrom`, `DateTo`, `Location`, `Logo`, `BarcodeLength`, `EventDate`, `EventTime`, `UpdateTriggerOne`, `UpdateTimeOne`, `UpdateTriggerTwo`, `UpdateTimeTwo`, `IsMealZone`, `DayNumber`, `SessionNumer`, `MealDays`, `MealsPerDay`, `Active`.

`Zones`: `ZID` unique, `AID`, `Number`, `Hidden`, `Lock`, `Active`, `Icon`, `ZTID`, `Name`, `Color`, `FromTime`, `ToTime`.

`Persons`: `AASID` unique, `AAID`, `AC`, `Ref`, `LastUpdate`, `FirstName`, `Surname`, `User_pic`, `Category`, `IDnumber`, `RoleColor`, `organisation`, `Role`, `Barcode`, `SCANID`, `aZones`.

`Food`: `ID` integer primary key autoincrement, `AASID`, `Day`, `Season`, `Time`.

`Checkin` is a CLR type only (`AASID`, `Name`, `Zone`, `Time`, `Allowed`, `NotAllowed`). It is not a table. `Scanmeal.Save_Report` constructs one and is not called.

### INSERT defect

Both `Person.save_to_db` overloads build the INSERT by closing the FirstName quote with `,'` too early, then starting another literal for Surname. The UPDATE in the same methods quotes each column separately and does not have that break. `ExecuteData` catches the failure. Callers treat a false update as "try insert" and ignore a false insert.

This is visible in source. It was not executed against SQLite for this document.

`GetFoodProfile` sets `profile.Season` from `DataReader["Day"]` rather than `DataReader["Season"]`. The SELECT that feeds it filters on `Season` correctly.

## HTTP

All live calls are HTTP GET with `WebClient` or, in the unused `CheckUpdatesAsync`, `HttpClient`. No header, no API key, no client certificate, no retry policy.

| Call | URL | Caller |
|---|---|---|
| Connectivity probe | `https://www.footprintapp.net/api/tourn/` | Header timer (1s), settings timer, download and refresh guards |
| Event list | `https://footprintapp.net/api/Accreditation/getevents` | `Setup.GetEventsData` |
| Applicants, paged | `https://footprintapp.net/api/accreditation/getapplicants/ac/{AID}/id/{AASID}` | `Setup.GetNewData` |
| Applicant updates | `https://footprintapp.net/api/accreditation/getapplicantsupdates/ac/{AID}/date/{lastUpdated}` | `Webservices.CheckUpdates` from the zone-screen thread |
| Images | `https://footprintapp.net/api/accreditation/getimages/ac/{AID}/id/{AAID}` | `Setup.GetProfileImages`, `Scan.Download_Image` |
| Unused full applicant dump | `https://footprintapp.net/api/accreditation/getapplicants/ac/{AID}` | `Webservices.GetNewData` (no live caller) |
| Unused updates | `https://footprintapp.net/api/accreditation/getupdates/ac/{AID}/date/{lastUpdated}` | `Webservices.CheckUpdatesAsync` (no live caller) |

Host spelling differs: the probe uses `www.footprintapp.net`. The data calls use `footprintapp.net`. Accreditation path casing differs: `Accreditation/getevents` versus `accreditation/getapplicants`.

`lastUpdated` is the file contents. The seed string written when the file is missing is `2018:09:29 08:00`. After a completed update the format is `yyyy-MM-dd HH:mm`. The value is placed in the path, not query-encoded in the method that builds the URL (`Webservices.CheckUpdates`). A space in the timestamp is left as a space in the `Uri` string.

Download completion for applicants expects JSON with a `data` array (`JsonObjects.data.Count`). Image completion expects a JSON array of objects with `User_pic` and `AAID`. The event list completion expects a JSON array (indexed in `ShowPage`). The response schemas are not declared as types; parsing uses `dynamic` except the unused `GetNewData` handler, which deserializes to `Person`.

Failure behaviour: most catches are empty. Applicant download sets "Unable to download data" on exception. The connectivity probe returns false. There is no user-visible HTTP status.

## Threads and timers

| Timer | Interval | Where | Work |
|---|---|---|---|
| Header clock and probe | 1 second | `header` | Clock labels and connectivity colour |
| Settings probe | `Interval` is never set | `Setup` | First successful probe starts the event download. See the note under this table |
| Scan result | 10 seconds | `Scan`, `Scanmeal` | Replace the page |
| Image refresh | 120 seconds | `Scan`, only when `WorkMode` is `ON` | Next missing image. Was 15 seconds in `43bc412` |
| Applicant refresh | 240 seconds | `Scan`, only when `WorkMode` is `ON` | `new Thread` calling `CheckUpdates`. Was 20 seconds in `43bc412` |

`Setup` does `Timer = new DispatcherTimer(); Timer.Tick += get_time; Timer.Start();` and never sets `Interval`. The WPF default `Interval` is 00:00:00, and a zero interval is not the same as "unset" if the property stays at its default. **Requires confirmation** against a running build: the settings tick may fire as fast as the dispatcher allows, and each tick calls `CheckForInternetConnection` until the first event download starts. The flag `_loadedEventLoading` stops repeat downloads. It does not stop the probe.

The update thread is not joined. The catch calls `thread_Update.Abort()`. `CheckUpdates` uses `WebClient` and writes the SQLite file off the UI thread while the UI may also open that file. No lock is taken around `Database`.

`Scan` calls `InitializeComponent` twice in the constructor.

## NFC

`using NFCSharp`. `startpulling` subscribes the first reader to `TagFound` and calls `StartPolling`. `Snapscan` reads `Tag.UID` and, when the string length is 11 and `nfcBusy` is 0, calls `UserProfile(code, 1)`.

Both constructors wrap `NFCHandler.Init` and `startpulling` in a block comment. On the zone page, `UserProfile` returns immediately unless the keyboard field `Barcode` is non-empty, so a tag callback would not reach the lookup even if init were enabled, until a wedge had left text in that field.

`Scanmeal.UserProfile` does use the argument, so the meal page would look up `SCANID` if init were uncommented. Its `Snapscan` also contains a second block that shows `MessageBox.Show(nfcBusy.ToString())` after a nested tag check. That block is still inside the method and is compiled. It runs only when a tag event is delivered.

## Audio

Zone page, at startup: two `SoundPlayer` objects load `{currentDirectory}\images\ok.wav` and `Bazz.wav` (`Directory.GetCurrentDirectory()`, not the assembly directory).

| Result | What plays |
|---|---|
| Zone grant (`Allowed`) | `SystemSounds.Asterisk`. The `OK_Mplayer.Play()` line is commented out, so `ok.wav` is loaded and not heard. |
| Zone deny (`NotAllowed`) | `Bazz.wav` via `No_Mplayer.Play()` (asynchronous). |
| `Scan.playSound_OK` / `Scan.playSound_No` | System beep, and `Bazz.wav` with `PlaySync`. Nothing calls these two methods. |
| Meal grant / deny | No sound. The calls to `playSound_OK` and `playSound_No` are inside comments. Those methods, if they ran, would look for `ok.wav` and `Bazz.wav` directly under `currentDirectory`, not under `images\`. |

NAudio is referenced and not used by these players.

## ClickOnce and signing

| Setting | Value |
|---|---|
| `PublishUrl` | `C:\Users\Abdurahmaan\Desktop\Evolve\` |
| `InstallFrom` | Disk |
| `UpdateEnabled` | false |
| `ApplicationRevision` | 12 |
| `ApplicationVersion` | `1.0.0.*` |
| `GenerateManifests` / `SignManifests` | true |
| `ManifestKeyFile` | `MagusEvents_TemporaryKey.pfx` |
| `ManifestCertificateThumbprint` | `3303FF50BC42030C479AA9CF011089320762D552` |

`.gitignore` ignores `*.pfx`. The key file is not in Git. A signed publish from a clean tree fails until the pfx is supplied. The publish URL is a user desktop path from the machine that last saved the project. It is not evidence of a current distribution server.

The removed `Build App/MagusEvents.application` and `MagusEvents_1_0_0_12` folder are the only evidence of a completed publish, and only at `43bc412`.

## Security

Observed in the tree. This is not a penetration test.

- No authentication on the desktop UI or on outbound HTTP.
- SQLite file and logs sit in `c:\temp_acc\` with no encryption in this code. Profile image payloads and the event logo (base64, which can be a picture of a person) are stored there.
- SQL is built by concatenation from the barcode, from API JSON, and from CSV fields.
- `SignManifests` is true, but the private key is not in the repository. The thumbprint is.
- Exceptions on the zone and meal lookup path can show `Exception.ToString()` in a message box, which includes the call stack.
- The connectivity probe and the data downloads run without TLS pinning. Certificate behaviour is the default `WebClient` behaviour. **Unknown** beyond that.

## Process, tests, and operations

| Area | What is in the repo |
|---|---|
| Tests | No test project, no test files. |
| CI | No `bitbucket-pipelines.yml`, no GitHub Actions, no Dockerfile. |
| Logging | `Console.WriteLine` in many methods. No log framework. |
| Monitoring | None. |
| Background service | None. Timers live inside the WPF process. |
| Configuration | No `appSettings`. Paths and URLs are literals. `WorkMode` is an in-memory `Application` property. `Properties\Settings.settings` is the empty generated user-settings file. |
| Environments | No dev/test/prod switch. Every URL is the production-looking `footprintapp.net` host. |
| Source control | Single `master`. Authors: Jaco Brits (initial README), siliconoverdrive (first stable), maanie (second stable). |

## Build notes (from the project file, not from a build run)

This onboarding did not compile the solution.

A build needs the .NET Framework 4.6 targeting pack, NuGet restore, and either removal of the `NFCSharp` reference or a DLL at the hint path. ClickOnce signing needs the pfx. `packages\` restore must provide the SQLite `.targets` import or the `EnsureNuGetPackageBuildImports` target errors.

## Relationship to magusEventsXamarin

Separate repository (`git@bitbucket.org:overdrive/maguseventsxamarin.git`), documented under `silicon_ark/magusEventsXamarin/`. Shared evidence: Footprint accreditation host, zone substring `312`, zone type `24`, `ok.wav` and `Bazz.wav`, author `maanie`, and the MagusEvents name. The Xamarin tree continues to 2020-08-17 and adds a settings PIN, Android/iOS projects, and a vehicle (VAP) mode this desktop tree does not have. This desktop tree has the meal scanner and the CSV import, which that document set does not describe as the same screens.

Whether one product replaced the other is **Unknown / Requires Confirmation**.
