Cross-platform Flutter app for employee endpoint security attestation on macOS, Windows, Linux, iOS, Android, and web. It collects device context and a lightweight endpoint protection snapshot, lets the employee review it, and sends a signed check-in to a central endpoint such as the included Google Sheets-backed Apps Script webhook.
- Owner name
- Owner email
- Endpoint name
- Hard disk encryption status
- Screensaver / screen lock status
- Firewall status
- Whether 1Password is installed
- macOS: automatic checks for FileVault, screen lock, firewall, and 1Password.
- Windows: automatic checks for BitLocker, screen saver lock, firewall, and 1Password.
- Linux: best-effort checks for disk encryption, GNOME screen lock, firewall, and 1Password. Linux reporting is conservative and may require manual review.
- iOS: device identity is collected, but security checks fall back to manual review because iOS does not expose these controls to regular apps.
- Android: device identity is collected, but security checks fall back to manual review in this first version for portability and policy simplicity.
- Web: browser identity is collected, and all security checks fall back to manual review because a browser app cannot inspect the host machine.
There is no clean portable API that lets a normal third-party app inspect all of these controls across desktop and mobile. This build uses automatic probes where the OS allows it and manual confirmation where it does not. That keeps the employee flow simple without pretending the mobile checks are more reliable than they are.
-
Install Flutter on a workstation that will build the app.
-
Install dependencies:
flutter pub get
-
Set up the central submission endpoint. A Google Apps Script example is included in
backend/google-apps-script/Code.gsand documented inbackend/google-apps-script/README.md. -
Run the app with your environment baked in:
flutter run -d macos \ --dart-define=ORGANIZATION_NAME="Helixiora" \ --dart-define=APP_VERSION="$(./scripts/git-version.sh)" \ --dart-define=SUBMISSION_ENDPOINT="https://script.google.com/macros/s/your-id/exec" \ --dart-define=SUBMISSION_SECRET="shared-secret-from-apps-script-properties"
The app window title and the footer version badge use APP_VERSION. For tagged builds, the recommended value is git describe --tags --always --dirty, which scripts/git-version.sh already wraps.
The included Apps Script flattens each submission into one spreadsheet column per JSON leaf using JSON pointer-style headers such as /owner/name and /checks/0/detectedStatus.
- New payload keys automatically create new columns in the header row.
- Array entries use numeric path segments.
- Keys containing
/or~are escaped so column names stay stable.
See backend/google-apps-script/README.md for setup details.
That README also documents updating an existing Apps Script deployment with clasp.
-
Install dependencies:
make bootstrap
-
Run the local quality gate:
make check
-
Install the versioned Git pre-commit hook:
make hooks-install
make check runs Dart format verification, the Apps Script verifier, flutter analyze, and flutter test.
It expects flutter, dart, and node to be available on your path.
If you use the Python pre-commit tool directly, pre-commit install and pre-commit run now work as well.
Windows artifacts must be built on a Windows host.
From PowerShell on a Windows machine:
./scripts/build-windows.ps1 -OrganizationName "Helixiora" -SubmissionEndpoint "https://script.google.com/macros/s/your-id/exec" -SubmissionSecret "shared-secret-from-apps-script-properties" -ZipArtifactIf -AppVersion is omitted, the script derives it from git describe --tags --always --dirty.
Output:
- Release folder:
build/windows/x64/runner/Release - Zip artifact:
build/windows/helixiora-endpoint-security-windows.zip
A manual workflow is included in .github/workflows/windows-build.yml.
Recommended repository settings:
- Repository variable
ORGANIZATION_NAME:Helixiora - Repository secret
SUBMISSION_ENDPOINT: your production submission URL - Repository secret
SUBMISSION_SECRET: the shared HMAC secret configured in Apps Script script properties
Then open Actions -> Build Windows -> Run workflow. The workflow builds the Windows release on windows-latest and uploads helixiora-endpoint-security-windows.zip as an artifact.
To build every supported target from GitHub Actions, use .github/workflows/build-all-platforms.yml.
It runs:
flutter analyzeflutter testflutter build webflutter build linux --releaseflutter build apk --releaseflutter build windows --releaseflutter build macos --releaseflutter build ios --release --no-codesign
Each artifact build injects APP_VERSION from the checked-out git tags, so the generated app exposes the build version in the window title and the footer.
Artifacts uploaded by the workflow:
helixiora-webhelixiora-linuxhelixiora-android-apkhelixiora-windowshelixiora-macoshelixiora-ios-unsigned
Recommended repository settings:
- Repository variable
ORGANIZATION_NAME:Helixiora - Repository secret
SUBMISSION_ENDPOINT: your production submission URL - Repository secret
SUBMISSION_SECRET: the shared HMAC secret configured in Apps Script script properties - Optional Android release signing secrets:
HELIXIORA_ANDROID_KEYSTORE_BASE64,HELIXIORA_ANDROID_KEYSTORE_PASSWORD,HELIXIORA_ANDROID_KEY_ALIAS, andHELIXIORA_ANDROID_KEY_PASSWORD
Open Actions -> Build All Platforms -> Run workflow to generate all artifacts in one run.
Pushing a tag that starts with v (for example v1.2.0) runs the same build matrix and attaches all platform artifacts as zip files to an automatically created GitHub release:
git tag v1.2.0
git push origin v1.2.0If Android signing secrets are omitted, the Android release APK is built unsigned. Local Android release signing uses the same values as Gradle properties or environment variables, with HELIXIORA_ANDROID_KEYSTORE pointing at the .jks file.
.github/workflows/quality.yml: runs formatting, Apps Script validation,flutter analyze, andflutter teston pushes and pull requests..github/workflows/pr-title.yml: checks pull request titles use Release Please-compatible Conventional Commit titles such asfeat:,fix:, orchore: release 1.2.3..github/dependabot.yml: keeps Flutterpubdependencies and GitHub Actions dependencies moving automatically.SECURITY.md: documents private vulnerability reporting and supported-version expectations..pre-commit-config.yaml: Pythonpre-commitconfiguration that runs the repository quality gate..githooks/pre-commit: versioned fallback hook that defers topre-commitwhen available.
- Launch the app.
- Review or fill in name, email, and endpoint name.
- Review the detected security checks.
- Override any check that needs manual correction.
- Submit.
lib/main.dart: app entry pointlib/src/app.dart: check-in screen state and review/submit flowlib/src/widgets/: the UI building blocks (check cards, desktop layout, review dialog, form)lib/src/inspector/endpoint_inspector.dart: platform-aware inspection orchestrationlib/src/inspector/desktop_probes.dart: desktop command executionbackend/google-apps-script/Code.gs: spreadsheet-backed webhook examplescripts/check-apps-script.mjs: local verification for the Apps Script flattener
- Submissions are signed with HMAC-SHA256 over the exact payload JSON string, using a shared secret baked into the build (
SUBMISSION_SECRET) and verified by the Apps Script backend (envelope schema v3). - The backend rejects envelopes older than 15 minutes and caches accepted signatures for 30 minutes, so captured requests cannot be replayed.
- The shared secret ships inside every distributed binary and is extractable by anyone with a copy of the app. The signature therefore proves a submission came from a build of this app, not from a specific employee or device. This is an attestation tool built on trust in employees, not tamper-proof evidence. If stronger provenance is ever needed, issue per-employee tokens out of band.
- Do not distribute the web build with a baked-in
SUBMISSION_SECRETto an audience broader than the secret itself: in a web build the secret is plainly readable in the served JavaScript by anyone who can open the URL. Ship the web build secretless (employees use Copy JSON) or keep its URL as restricted as the secret.
- The desktop app depends on local OS commands, so it is intended for normal internal distribution, not a locked-down app store sandbox.
- The macOS runner is intentionally not sandboxed, because the automatic checks rely on local system commands.
- Linux checks are heuristic because desktop environments and firewall stacks vary.
- Windows screen-lock detection covers the legacy secure screen saver and the
InactivityTimeoutSecsmachine policy; sleep sign-in and dynamic lock cannot be read, so such setups fall back to employee confirmation. - iOS and Android cannot fully self-inspect these settings without deeper MDM or enterprise integration.
- This is an attestation tool, not an enforcement tool. For stronger guarantees, pair it with MDM or endpoint management.
flutter analyze: passesflutter test: passesflutter build macos --debug: passesflutter build macos: passesflutter build web: passes- Android builds are currently blocked on this machine because the Android SDK
cmdline-toolscomponent is missing. - iOS simulator builds are currently blocked on this machine because the iOS simulator runtime is not installed in Xcode.
- Windows builds require a Windows host. Local support is in
scripts/build-windows.ps1and CI support is in.github/workflows/windows-build.yml. - Full multi-platform CI is in
.github/workflows/build-all-platforms.yml.