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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions