DevTools
permission_guard Pro
- Tier
- Proversion 1.1.6
- Command
archipelago generate permission_guard- Generates
devtools/scripts/permission_guard
- Depends on
- monorepo_toolkitgenerate these first
Detects permission changes in compiled Android APK and iOS IPA artifacts. Catches permissions a plugin adds transitively — which source-XML diffing misses — by diffing what's actually declared in the built artifact. Adds the
permission-guardcommand to the basemonorepo_toolkit.
Requires the base monorepo_toolkit brick to already be generated.
Variables
| Variable | Type | Default | Description |
|---|---|---|---|
| appName | string | MyApp | The name of your application |
| isForMonorepo | boolean | true | Whether this is being generated as part of a monorepo |
Usage
Interactive
archipelago generate permission_guardNon-interactive (CI)
archipelago generate permission_guard --config my_config.jsonGenerated Structure
devtools/
└── scripts/
└── permission_guard/
├── lib/
│ ├── permission_guard.dart
│ └── src/
│ ├── commands/
│ │ ├── android_command.dart
│ │ ├── ios_command.dart
│ │ ├── permission_guard_command.dart
│ │ └── update_baseline_command.dart
│ ├── models/
│ │ └── permission_guard_config.dart
│ └── services/
│ ├── android_permission_service.dart
│ ├── ios_permission_service.dart
│ └── permission_guard_service.dart
└── pubspec.yaml
.permissionguard.yaml # config, scaffolded at workspace root
permission_baseline/
├── android.txt # scaffolded EMPTY — see below
└── ios.txt # scaffolded EMPTY — see belowThe empty baseline is deliberate (since 1.1.0): the first real build fails and prints the app's actual declared permissions, forcing an explicit, reviewed baseline-acceptance decision rather than starting from an unaudited default.
Config
.permissionguard.yaml, scaffolded at the workspace root:
fail_on_new: true # fail the build when a new permission is detected
warn_on_removed: false # only warn (don't fail) when a permission is removed
android_baseline_path: permission_baseline/android.txt
ios_baseline_path: permission_baseline/ios.txtandroid_baseline_path/ios_baseline_path are read by AndroidCommand/IosCommand/UpdateBaselineCommand as fallbacks whenever --baseline/--output isn't passed explicitly (fixed in 1.1.0 — before that the config keys were parsed but silently ignored, and each command hardcoded its own CLI defaults instead).
CLI
# Diff a built APK's permissions against the Android baseline.
dart run monorepo_toolkit permission-guard android --apk <path-to-apk>
# Diff a built IPA's permissions against the iOS baseline.
dart run monorepo_toolkit permission-guard ios --ipa <path-to-ipa>
# Accept the current build's permissions as the new baseline.
dart run monorepo_toolkit permission-guard update-baseline --platform android --artifact <path>
dart run monorepo_toolkit permission-guard update-baseline --platform ios --artifact <path>DI and wiring notes
post_gen.dart (when isForMonorepo: true) adds devtools/scripts/permission_guard to the workspace, adds a path dependency to devtools/monorepo_toolkit/pubspec.yaml, and injects PermissionGuardCommand (a Command<int> with android/ios/update-baseline subcommands) into command_runner.dart at the // --- Pro Commands --- marker. This is CLI command registration, not app-runtime GetIt DI — there's no archipelago: di_modules block here, since permission_guard never runs inside the Flutter app itself.
Dependencies
- Hard prerequisite: base
monorepo_toolkitbrick must already be generated (pre_gen.dartdoes no self-generation — it does nothing at all beyond accepting the direct brick.yaml vars). - When
isForMonorepo: false,post_gen.dartskips all workspace/command-runner wiring and just scaffolds the package standalone.
Wiring into CI
Not patched automatically — build-android.yml/build-ios.yml's exact shape varies too much per project (custom steps, non-GitHub CI) to touch safely, unlike the stable-marker command_runner.dart injection. post_gen.dart prints the exact snippets to add:
# .github/workflows/build-android.yml, after the APK is built
# (only the non-Play-Store/APK path -- apkanalyzer has no AAB support)
- name: Check Android permissions
if: inputs.track == ''
run: |
cd ../..
dart run monorepo_toolkit permission-guard android --apk apps/<app>/build/app/outputs/flutter-apk/app-$FLAVOR-release.apk# .github/workflows/build-ios.yml, after the IPA is built
- name: Check iOS permissions
run: |
cd ../..
dart run monorepo_toolkit permission-guard ios --ipa apps/<app>/build/ios/ipa/<app>.ipaKnown Limitations
- CI wiring is print-only guidance, not an automated patch — you add the workflow steps yourself.
- Android AAB (Play Store) builds aren't covered —
apkanalyzerhas no AAB support, only APK. - The scaffolded baselines start empty on purpose, so the first CI run after generating this brick is expected to fail until you run
update-baselineand commit the result.
Changelog
Run archipelago brick info permission_guard to see the latest published version. Enterprise customers can read the full CHANGELOG.md in the brick source repository.