Skip to content
Back to archipelago.banuacoder.com

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-guard command to the base monorepo_toolkit.

Requires the base monorepo_toolkit brick to already be generated.

Variables ​

VariableTypeDefaultDescription
appNamestringMyAppThe name of your application
isForMonorepobooleantrueWhether this is being generated as part of a monorepo

Usage ​

Interactive ​

bash
archipelago generate permission_guard

Non-interactive (CI) ​

bash
archipelago generate permission_guard --config my_config.json

Generated Structure ​

text
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 below

The 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:

yaml
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.txt

android_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 ​

bash
# 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_toolkit brick must already be generated (pre_gen.dart does no self-generation — it does nothing at all beyond accepting the direct brick.yaml vars).
  • When isForMonorepo: false, post_gen.dart skips 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:

yaml
# .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
yaml
# .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>.ipa

Known 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 — apkanalyzer has 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-baseline and 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.