DevTools
Audit the artifact that actually ships.
$ composer require all1web/nativephp-devtools
Developer tools for NativePHP Mobile apps: a host-side release audit that opens the artifact that actually ships, and an on-device inspector for dev builds.
- Release audit opens the real build artifact, not your source tree
- CI-friendly JSON output via --json
- On-device inspector for dev builds
Documentation
nativephp-devtools
Developer tools for NativePHP Mobile apps — dev builds only.
Nobody checks the seam between what your Laravel project contains and what got
zipped into the app package. MobSF can crack an APK but has no concept of a
Laravel bundle, auth.json, cleanup_env_keys or a plugin manifest.
native:debug never opens the artifact at all.
devtools:audit opens the artifact that actually ships and tells you what is
in it.
composer require --dev all1web/nativephp-devtools
php artisan devtools:audit
What it does
Two halves, one package:
- Release audit (
devtools:audit) — opens the shipped bundle and the generated native project, and reports what leaked, what is misconfigured, and what the app declares. This is v1. - Device inspector — an on-device UI for dev builds. Not in v1; two questions about EDGE routing have to be answered on hardware first, and guessing at them would be worse than waiting.
Seven checks run over the artifact: bundle leak scan, .env residue, dependency
and native-surface analysis, Android release hardening, composer advisories,
capability truth, and a store-submission evidence pack. See
docs/REFERENCE.md.
Why the artifact and not your config
The two code paths that build a bundle use different exclusion matchers, and on
Windows the zip step ignores cleanup_exclude_files entirely — the only filter
is robocopy /XD, which takes directories, so a file pattern silently does
nothing. Your config describes what was meant to happen. Only the bundle
records what did.
Run against a real production bundle of 57,722 entries, the audit found
plaintext third-party licence credentials in a bundled auth.json; APP_KEY,
MAIL_PASSWORD and REDIS_PASSWORD surviving cleanup_env_keys; the complete
commit history of three private packages pulled in through composer path
repositories; two vendored packages shipping their own vendor/ trees totalling
33,649 files including Pest and PHPUnit; and a shipped SQLite database. It took
six seconds.
Exit codes
| Code | Meaning |
|---|---|
0 |
Ran, found nothing at or above the threshold |
1 |
Ran, found something |
2 |
Could not run |
2 is deliberately not 0. A CI step that reads "bundle not found" as a pass
is worse than no CI step at all.
The command does not gate a release and does not pretend to — the framework's build-hook runner warns on a non-zero hook exit and carries on, so no build hook can stop anything. Wire it into your own pipeline:
php artisan devtools:audit --json > audit.json || exit 1
Secret values are redacted by default. --show-values exists, and the docs tell
you not to use it in CI.
This never ships to production
There is no hidden mode, no secret key, no production admin surface. The package
is require-dev, contributes zero native code — no Kotlin, no Swift, no
manifest nodes, no bridge functions — and its service provider registers nothing
at all outside a development environment with APP_DEBUG on.
Zero native code is a security property rather than a style choice. The plugin
compiler does not consult the composer section a package was installed from, so
a plugin contributing native code ships its Kotlin into release builds even as
require-dev, while --no-dev strips the PHP that was supposed to gate it. A
test fails the build if this package ever grows a .kt, a .swift or a bridge
function. The audit reports that exact failure in other packages.
Removal
Uninstall is one command, with nothing else to undo:
composer remove --dev all1web/nativephp-devtools
No plugin allowlist entry to clean up and no native:install --force
afterwards, because there is no native code to unregister. That is verified
rather than assumed: the framework filters on composer type before it consults
its allowlist, so this package is absent from plugin discovery even if you
add its service provider to NativeServiceProvider::plugins() by hand.
Registration is not just unnecessary, it is impossible.
If you do nothing, a release build already strips it: native:build runs
composer install --no-dev. Debug builds keep it deliberately, and that is
fine — nothing in a debug bundle reaches a user.
If you want to be certain, keep it installed but exclude it from bundles:
// config/nativephp.php
'cleanup_exclude_files' => [
// keep the framework defaults
'storage/framework/sessions',
'storage/framework/cache',
'storage/framework/testing',
'storage/logs',
// and exclude this package
'vendor/all1web/nativephp-devtools',
],
Then prove it. Re-run php artisan devtools:audit and confirm the
self-present finding is gone. Do not take the config's word for it — on
Windows those patterns are ignored at zip time. The audit reports its own
presence in any bundle it analyses, because a tool that finds everyone else's
leaked dev dependencies while staying quiet about its own is a defect.
php artisan devtools:doctor reports the gate state, which composer section the
package landed in, and this removal path.
Documentation
- DESIGN.md — what it deliberately does not do, and why
- REFERENCE.md — commands, checks, findings, corpus format
- PLATFORM-NOTES.md — verified build behaviour, and the limits of what an artifact can tell you
- STORE-REVIEW.md — the evidence pack, and its boundary
Requirements
PHP 8.2+, Laravel 10/11/12, ext-zip. nativephp/mobile is not required: the
audit reads build artifacts, so the test suite runs off-device.
Status: v1 in development. Half A complete and tested; Half B pending on-device verification. No public claims yet.