Skip to content

fix: emit project-relative callable paths for portable deterministic artifacts #61

Description

@rahlk

Problem

The output uses two incompatible path conventions:

  • TSModule.file_path and TSSynthesizedCallable.path are project-relative POSIX paths;
  • every regular TSCallable.path is the absolute host path returned by ts-morph.

This leaks checkout-specific host information and makes otherwise identical analysis artifacts differ across machines/containers. It also forces consumers to special-case regular versus synthesized callables.

Reproduction

In the OWASP Juice Shop 6244c59 export:

  • all 1,100 regular callable paths are absolute, rooted at the local checkout;
  • all 888 synthesized callable paths are relative;
  • all 386 module file_path values are relative.

Example:

{
  "symbol_table": {
    "app.ts": {
      "file_path": "app.ts",
      "functions": {
        "app.app": {
          "path": "/Users/.../juice-shop/app.ts"
        }
      }
    }
  },
  "synthesized_callables": {
    "...": { "path": "server.ts" }
  }
}

src/syntactic_analysis/builders.ts assigns sigNode.getSourceFile().getFilePath() / filePath directly, while module and synthesized builders normalize through fileKeyOf(...).

Expected behavior

Source identity in the portable artifact should use one project-relative POSIX convention. Absolute paths may be useful in local diagnostics, but should not be serialized as canonical data.

Acceptance criteria

  • Serialize TSCallable.path using the same project-relative fileKey convention as modules and synthesized callables.
  • Cover normal functions, methods, accessors, nested callables, and implicit constructors.
  • Ensure no serialized canonical path starts with the analysis input root.
  • Add a determinism test that analyzes identical source trees under two different temporary parent directories and compares canonical JSON after excluding timestamps (ideally byte-for-byte if timestamp metadata permits).
  • Preserve absolute paths only in transient diagnostics if needed.
  • Coordinate any schema/migration note with analyzer-envelope issue feat: analyzer{name,version} schema envelope #29.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingfixBug fix

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions