* fix(apple): limit already-loaded reuse to rpath dependencies
dyld reuses an already-loaded image by install name only for @rpath/
dependencies (Loader.cpp:802-816) and evaluates other dependency forms
against their expanded path for each loader. When multiple images in
different directories depend on @loader_path/ libraries sharing an
install name, checking loaded images before candidate expansion caused
subsequent loaders to bind to the first loaded image's copy or appear
resolved when their own copy was absent.
Limit byInstallName registration and lookup to install names that start
with @rpath/, leaving caller-relative and literal dependencies to expand
and evaluate their own candidate paths.
Signed-off-by: Vinícius DS Andrade <95101505+viniciusdsandrade@users.noreply.github.com>
* test(apple): verify loader_path dependencies across isolated directories
Assert that multiple images depending on @loader_path/ libraries with
the same install name do not reuse already-loaded images across loaders.
When the second loader's helper is absent, its candidate path is absent
and dyld reports required-load-unresolved; when both helpers exist, each
loader resolves to its own directory.
Signed-off-by: Vinícius DS Andrade <95101505+viniciusdsandrade@users.noreply.github.com>
---------
Signed-off-by: Vinícius DS Andrade <95101505+viniciusdsandrade@users.noreply.github.com>
Deliver complete Evidence directly through MCP with required nullable analysis profiles and immutable per-server delivery settings. Bind selected environments at construction and require typed cleanup outcomes with retained retry ownership.
Remove test-only routing, duplicate session and snapshot metadata, producer-field repairs, and ambiguous provider arguments. Separate artifact byte identity from occurrence classification and retain typed source-map and partial native facts across CLI, MCP, and verifier consumers.
BREAKING CHANGE: obsolete Evidence envelopes, session aliases, incomplete snapshots, and missing normalized producer facts are no longer accepted.
- Edges below a conditional fallback now carry loader_conditional, reuse of
a conditional image by install name is conditional, and their findings say
they apply only if that image loads.
- Hash each traced image only if it is still the file whose headers were
parsed (device, inode, size and change times), before and after hashing.
- Resolve explicit roots segment by segment, so a root below a symlinked
directory that points outside the analyzed root is rejected.
- Require a complete 16-byte LC_CODE_SIGNATURE command.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Address review findings in trace_dylib_resolution:
- Resolve LC_LAZY_LOAD_DYLIB dependencies without traversing them, since
dyld loads them on first use. An unresolved one becomes
`lazy-load-unresolved`, not a launch failure.
- Accept FAT tables up to 128 records, as target opening does. A table
that names no Mach-O CPU type, such as a Java class file, is not
Mach-O.
- Require 8-byte load-command alignment in 64-bit images. 1,508 real
slices still match otool.
- Report EACCES/EPERM while probing, reading, or hashing as an
`unavailable` failure naming the code and path, rather than generic
io.
Findings and limitations move to dylibResolutionFindings.ts to keep the
resolver under the module size limit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Address review findings in trace_dylib_resolution:
- Choose child slices by dyld's graded architectures, so an x86_64h
process loads a generic x86_64 slice instead of reporting
architecture-missing.
- Read FAT containers with the byte-swapped FAT_CIGAM and FAT_CIGAM_64
magics, which target opening already accepts.
- Report string-bearing load commands too short to hold their string
offset as malformed instead of failing with a RangeError.
- Keep recognized but unsupported images as an `unsupported` candidate
outcome. It is undeterminable like an outside-root path, not
malformed.
- List Mach-O files that do not parse during root enumeration as
unparsed images, so coverage is partial rather than silently complete.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add trace_dylib_resolution (CLI trace-dylib-resolution) to the artifact
family. For the active Mach-O, or every executable in the active .app
(the main app, XPC services, extensions, login items, helpers), it
reports which file each dylib load reaches and how.
A pure TypeScript reader decodes FAT and Mach-O load commands:
LC_LOAD/WEAK/REEXPORT/LAZY/UPWARD_DYLIB, including the newer
dylib_use_command encoding with weak, re-export, upward and delayed-init
flags, plus LC_ID_DYLIB, LC_RPATH, LC_DYLD_ENVIRONMENT and code-signature
presence. Malformed tables are reported with the failing command instead
of being guessed.
Resolution follows dyld:
- @executable_path comes from each process root;
- @loader_path comes from the loading image, or from the owner of the
LC_RPATH entry being expanded;
- @rpath searches the loader's rpaths first, then up the load chain;
- dependencies load dependents-first in load-command order, once per
process, and a matching install name reuses an already loaded image;
- symlinks are followed inside the analyzed root, and escapes stop.
Every candidate path is reported with its outcome. Each edge resolves to
resolved, conditional (an outside-root candidate such as /usr/lib/swift
precedes), unresolved, or undetermined. Absolute and shared-cache system
paths are never checked against the host. Derived findings cover
unresolved required or weak loads, absent earlier @rpath candidates (with
library validation left unknown), and LC_DYLD_ENVIRONMENT.
verify:macos-bundle now also:
- checks every traced image against otool -l;
- asserts each resolution status on a clang-built fixture that adds a
missing Overrides rpath, an absolute rpath, and a delay-init library;
- compares the predicted load order of two process roots with what dyld
loads under DYLD_PRINT_LIBRARIES.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Directory, ZIP, and DMG inventories can hold installers, disk-image
extras, and AppleDouble sidecars beside the app. Those components were
classified as the application's frameworks, libraries, JavaScript, and
metadata, and fed runtime families and bridge candidates. For these
formats, components outside every application root are now left out,
with a limitation that counts them. IPA projection is unchanged.
A selected directory whose name ends in .app is now its own root by
identity, so an empty or partial inventory still reports it. iOS is
claimed only for shallow roots that have an Info.plist, so an empty root
reports no platform.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
project_apple_application_graph accepted only IPA inventories. It now
also projects macOS .app directories and ZIP or DMG inventories that
contain applications. It reports application roots, platforms, and
every nested bundle with its path-convention role, layout, parent,
Info.plist path, executable candidates, and signing paths:
- roles: app extensions, XPC services (including inside frameworks),
frameworks, login items, system and driver extensions, plug-ins,
resource bundles, and helper or nested applications;
- privileged helpers in Contents/Library/LaunchServices and launchd
plists in Contents/Library/LaunchAgents or LaunchDaemons;
- direct files of Contents/Helpers;
- symlinks by path. Their targets are not inventoried, so versioned
frameworks are described through their real Versions/<version>/
directories.
AppleDouble sidecars (._* and __MACOSX/) are excluded from roles. A DMG
whose contents could not be inventoried is reported as partial. Other
inventory formats remain input errors. The projection still reads no
plist or CMS semantics; it points callers at inspect_plist.
The result schema is additive. projection_id now covers the new fields,
so IPA projection IDs differ from earlier versions.
verify:macos-bundle compiles a source-owned app with clang (CLT only).
It packs it as a directory, a ditto ZIP, and an APFS DMG, and checks
identical anatomy through the CLI with stdio MCP parity. It runs in the
macOS CI job.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(application): wire Android and Apple inventory graph tools
Expose project_android_application_graph and project_apple_application_graph
through CLI and MCP so authenticated inventory Evidence can be projected
without a provider launch.
* fix(application): use producer root occurrence IDs in graph examples
Catalog examples constructed root occurrence IDs from artifact_id +
logical_path, but inventory validation authenticates "." with
{ root: root_artifact_id }. Align the examples and regenerate catalogs
after rebasing onto main (application family count 11).
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>