cg-code-graph 0.21.0__tar.gz → 0.21.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (375) hide show
  1. {cg_code_graph-0.21.0/cg_code_graph.egg-info → cg_code_graph-0.21.1}/PKG-INFO +1 -1
  2. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/__init__.py +1 -1
  3. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/core/redact.py +46 -21
  4. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/laravel/plugin.py +1 -1
  5. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/surface.py +2 -2
  6. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1/cg_code_graph.egg-info}/PKG-INFO +1 -1
  7. cg_code_graph-0.21.1/tests/test_redact_salt.py +235 -0
  8. cg_code_graph-0.21.0/tests/test_redact_salt.py +0 -97
  9. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/LICENSE +0 -0
  10. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/MANIFEST.in +0 -0
  11. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/README.md +0 -0
  12. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/__main__.py +0 -0
  13. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/affected.py +0 -0
  14. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/agent_rules.py +0 -0
  15. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/agents.py +0 -0
  16. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/aitools.py +0 -0
  17. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/android_ipc.py +0 -0
  18. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/apple_ipc.py +0 -0
  19. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/apps.py +0 -0
  20. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/blindspots.py +0 -0
  21. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/bridges.py +0 -0
  22. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/brokers.py +0 -0
  23. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/cli.py +0 -0
  24. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/concepts.py +0 -0
  25. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/config.py +0 -0
  26. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/core/__init__.py +0 -0
  27. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/core/cache.py +0 -0
  28. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/core/detect.py +0 -0
  29. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/core/env.py +0 -0
  30. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/core/extractors.py +0 -0
  31. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/core/fsutil.py +0 -0
  32. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/core/generated.py +0 -0
  33. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/core/model.py +0 -0
  34. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/core/paths.py +0 -0
  35. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/core/plugin.py +0 -0
  36. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/core/store.py +0 -0
  37. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/core/syntax_errors.py +0 -0
  38. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/coverage.py +0 -0
  39. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/dart_isolates.py +0 -0
  40. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/doctor.py +0 -0
  41. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/explore.py +0 -0
  42. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/external.py +0 -0
  43. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/graphql.py +0 -0
  44. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/guard_facts.py +0 -0
  45. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/hooks.py +0 -0
  46. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/indexer.py +0 -0
  47. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/insecure_transport.py +0 -0
  48. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/jobs.py +0 -0
  49. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/link.py +0 -0
  50. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/lint_async.py +0 -0
  51. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/local_ipc.py +0 -0
  52. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/local_sockets.py +0 -0
  53. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/mcp_install.py +0 -0
  54. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/mcp_server.py +0 -0
  55. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/parity.py +0 -0
  56. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/parity_structure.py +0 -0
  57. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/payload.py +0 -0
  58. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plans.py +0 -0
  59. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/platform_scan.py +0 -0
  60. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/platforms.py +0 -0
  61. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/__init__.py +0 -0
  62. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/astro/__init__.py +0 -0
  63. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/astro/content.py +0 -0
  64. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/astro/plugin.py +0 -0
  65. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/cfamily/__init__.py +0 -0
  66. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/cfamily/plugin.py +0 -0
  67. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/cfamily/syntax.py +0 -0
  68. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/dart/__init__.py +0 -0
  69. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/dart/bridges.py +0 -0
  70. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/dart/extractor/bin/extract.dart +0 -0
  71. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/dart/extractor/pubspec.lock +0 -0
  72. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/dart/extractor/pubspec.yaml +0 -0
  73. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/dart/http.py +0 -0
  74. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/dart/models.py +0 -0
  75. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/dart/plugin.py +0 -0
  76. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/dart/program.py +0 -0
  77. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/django/__init__.py +0 -0
  78. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/django/extras.py +0 -0
  79. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/django/models.py +0 -0
  80. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/django/plugin.py +0 -0
  81. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/django/schemas.py +0 -0
  82. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/django/shapes.py +0 -0
  83. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/django/urls.py +0 -0
  84. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/express/__init__.py +0 -0
  85. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/express/plugin.py +0 -0
  86. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/flutter/__init__.py +0 -0
  87. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/flutter/plugin.py +0 -0
  88. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/java/__init__.py +0 -0
  89. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/java/exact.py +0 -0
  90. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/java/plugin.py +0 -0
  91. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/jvm/__init__.py +0 -0
  92. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/jvm/interop.py +0 -0
  93. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/jvm/spring.py +0 -0
  94. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/kotlin/__init__.py +0 -0
  95. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/kotlin/exact.py +0 -0
  96. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/kotlin/plugin.py +0 -0
  97. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/kotlin/reparse.py +0 -0
  98. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/laravel/__init__.py +0 -0
  99. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/laravel/broadcast.py +0 -0
  100. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/laravel/tests.py +0 -0
  101. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/laravel/values.py +0 -0
  102. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/native/__init__.py +0 -0
  103. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/native/gates.py +0 -0
  104. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/native/runner.py +0 -0
  105. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/native/scipread.py +0 -0
  106. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/native/ts.py +0 -0
  107. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/nest/__init__.py +0 -0
  108. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/nest/plugin.py +0 -0
  109. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/nextjs/__init__.py +0 -0
  110. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/nextjs/plugin.py +0 -0
  111. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/nuxt/__init__.py +0 -0
  112. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/nuxt/plugin.py +0 -0
  113. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/php/__init__.py +0 -0
  114. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/php/external.py +0 -0
  115. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/php/extractor/composer.json +0 -0
  116. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/php/extractor/composer.lock +0 -0
  117. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/php/extractor/extract.php +0 -0
  118. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/php/gating.py +0 -0
  119. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/php/http_client.py +0 -0
  120. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/php/inline_guards.py +0 -0
  121. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/php/plugin.py +0 -0
  122. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/php/strings.py +0 -0
  123. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/python/__init__.py +0 -0
  124. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/python/aitools.py +0 -0
  125. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/python/external.py +0 -0
  126. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/python/fields.py +0 -0
  127. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/python/plugin.py +0 -0
  128. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/python/refs.py +0 -0
  129. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/python/roots.py +0 -0
  130. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/python/socketio.py +0 -0
  131. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/python/subproc.py +0 -0
  132. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/python/tests.py +0 -0
  133. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/python/values.py +0 -0
  134. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/pyweb/__init__.py +0 -0
  135. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/pyweb/plugin.py +0 -0
  136. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/pyweb/values.py +0 -0
  137. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/rust/__init__.py +0 -0
  138. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/rust/cargo.py +0 -0
  139. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/rust/plugin.py +0 -0
  140. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/rust/syntax.py +0 -0
  141. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/scip/__init__.py +0 -0
  142. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/scip/importer.py +0 -0
  143. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/scip/scip.proto +0 -0
  144. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/scip/scip_pb2.py +0 -0
  145. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/stubs/__init__.py +0 -0
  146. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/stubs/plugins.py +0 -0
  147. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/swift/__init__.py +0 -0
  148. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/swift/baseurl.py +0 -0
  149. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/swift/exact.py +0 -0
  150. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/swift/indexstore.py +0 -0
  151. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/swift/packages.py +0 -0
  152. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/swift/plugin.py +0 -0
  153. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/ts/__init__.py +0 -0
  154. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/ts/baseurl.py +0 -0
  155. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/ts/extractor/extract.mjs +0 -0
  156. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/ts/extractor/fw.mjs +0 -0
  157. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/ts/extractor/package-lock.json +0 -0
  158. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/ts/extractor/package.json +0 -0
  159. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/ts/extractor/rr.mjs +0 -0
  160. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/ts/nav.py +0 -0
  161. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/ts/plugin.py +0 -0
  162. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/ts/react_router.py +0 -0
  163. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/tsweb/__init__.py +0 -0
  164. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/tsweb/common.py +0 -0
  165. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/plugins/tsweb/data.py +0 -0
  166. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/presets/__init__.py +0 -0
  167. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/presets/c_cpp.yaml +0 -0
  168. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/presets/common.yaml +0 -0
  169. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/presets/dart.yaml +0 -0
  170. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/presets/django-ninja.yaml +0 -0
  171. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/presets/django.yaml +0 -0
  172. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/presets/djangorestframework.yaml +0 -0
  173. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/presets/express.yaml +0 -0
  174. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/presets/java.yaml +0 -0
  175. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/presets/kotlin.yaml +0 -0
  176. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/presets/laravel.yaml +0 -0
  177. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/presets/nest.yaml +0 -0
  178. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/presets/nextjs.yaml +0 -0
  179. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/presets/nuxt.yaml +0 -0
  180. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/presets/php.yaml +0 -0
  181. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/presets/python.yaml +0 -0
  182. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/presets/react-router.yaml +0 -0
  183. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/presets/rust.yaml +0 -0
  184. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/presets/spring.yaml +0 -0
  185. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/presets/swift.yaml +0 -0
  186. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/presets/typescript.yaml +0 -0
  187. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/process_runs.py +0 -0
  188. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/protocols/__init__.py +0 -0
  189. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/protocols/builtin.py +0 -0
  190. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/protocols/matchers.py +0 -0
  191. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/protocols/view.py +0 -0
  192. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/query.py +0 -0
  193. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/realtime.py +0 -0
  194. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/realtime_events.py +0 -0
  195. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/realtime_native.py +0 -0
  196. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/realtime_ws.py +0 -0
  197. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/roundtrip.py +0 -0
  198. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/routes.py +0 -0
  199. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/rpc.py +0 -0
  200. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/sdk_systems.py +0 -0
  201. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/sockets.py +0 -0
  202. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/ssrf_input.py +0 -0
  203. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/starters.py +0 -0
  204. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/tests_index.py +0 -0
  205. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/udp_apps.py +0 -0
  206. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/viz/__init__.py +0 -0
  207. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/viz/graph.py +0 -0
  208. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/viz/server.py +0 -0
  209. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/viz/static/app.css +0 -0
  210. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/viz/static/app.js +0 -0
  211. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/viz/static/index.html +0 -0
  212. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/viz/static/layered.js +0 -0
  213. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/viz/static/vendor/VERSIONS.txt +0 -0
  214. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/viz/static/vendor/cose-base.js +0 -0
  215. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/viz/static/vendor/cytoscape-fcose.js +0 -0
  216. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/viz/static/vendor/cytoscape.min.js +0 -0
  217. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/viz/static/vendor/layout-base.js +0 -0
  218. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/viz/tools/package-lock.json +0 -0
  219. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/viz/tools/package.json +0 -0
  220. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/viz/tools/shoot.mjs +0 -0
  221. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/watch.py +0 -0
  222. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/webhook_subs.py +0 -0
  223. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/webhooks.py +0 -0
  224. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph/xcode.py +0 -0
  225. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph.egg-info/SOURCES.txt +0 -0
  226. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph.egg-info/dependency_links.txt +0 -0
  227. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph.egg-info/entry_points.txt +0 -0
  228. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph.egg-info/requires.txt +0 -0
  229. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/cg_code_graph.egg-info/top_level.txt +0 -0
  230. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/pyproject.toml +0 -0
  231. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/setup.cfg +0 -0
  232. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_affected.py +0 -0
  233. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_agents_install.py +0 -0
  234. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_agents_md.py +0 -0
  235. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_ai_tools.py +0 -0
  236. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_android_ipc.py +0 -0
  237. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_apple_ipc.py +0 -0
  238. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_astro.py +0 -0
  239. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_astro_content.py +0 -0
  240. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_astro_server.py +0 -0
  241. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_bridges.py +0 -0
  242. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_bridges_pigeon_monorepo.py +0 -0
  243. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_brokers.py +0 -0
  244. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_cache_clean.py +0 -0
  245. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_cache_invalidation.py +0 -0
  246. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_cache_migration.py +0 -0
  247. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_channels_tests.py +0 -0
  248. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_cli_output.py +0 -0
  249. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_completeness.py +0 -0
  250. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_config_extras.py +0 -0
  251. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_coverage.py +0 -0
  252. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_coverage_ts_hint.py +0 -0
  253. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_dart_isolates.py +0 -0
  254. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_dispatch_interfaces.py +0 -0
  255. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_django_flutter.py +0 -0
  256. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_docs_languages.py +0 -0
  257. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_docs_links.py +0 -0
  258. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_echo_ref.py +0 -0
  259. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_echo_wrapper.py +0 -0
  260. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_elysia.py +0 -0
  261. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_enum_constants.py +0 -0
  262. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_env.py +0 -0
  263. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_explore.py +0 -0
  264. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_external.py +0 -0
  265. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_fp_batch.py +0 -0
  266. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_gating.py +0 -0
  267. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_generated.py +0 -0
  268. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_graphql.py +0 -0
  269. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_hooks.py +0 -0
  270. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_impact_overrides.py +0 -0
  271. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_index_isolation.py +0 -0
  272. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_inherited_overrides.py +0 -0
  273. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_inline_guards.py +0 -0
  274. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_java.py +0 -0
  275. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_java_exact.py +0 -0
  276. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_jobs.py +0 -0
  277. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_js_refs.py +0 -0
  278. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_js_runtime.py +0 -0
  279. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_kotlin.py +0 -0
  280. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_kotlin_binding.py +0 -0
  281. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_kotlin_exact.py +0 -0
  282. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_kotlin_fields.py +0 -0
  283. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_kotlin_mixed.py +0 -0
  284. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_kotlin_nav_consts.py +0 -0
  285. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_kotlin_props.py +0 -0
  286. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_laravel_determinism.py +0 -0
  287. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_laravel_resources.py +0 -0
  288. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_lint_async.py +0 -0
  289. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_local_ipc.py +0 -0
  290. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_local_sockets.py +0 -0
  291. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_mcp.py +0 -0
  292. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_mcp_index.py +0 -0
  293. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_mcp_install.py +0 -0
  294. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_native_cfamily.py +0 -0
  295. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_native_concurrency.py +0 -0
  296. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_native_rust.py +0 -0
  297. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_nuxt_import_dirs.py +0 -0
  298. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_nuxt_rootsrc.py +0 -0
  299. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_packaging.py +0 -0
  300. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_parity.py +0 -0
  301. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_parity_structure.py +0 -0
  302. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_php_http.py +0 -0
  303. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_php_props.py +0 -0
  304. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_plain_js.py +0 -0
  305. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_plans.py +0 -0
  306. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_platform_gaps.py +0 -0
  307. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_platform_type_variants.py +0 -0
  308. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_platforms.py +0 -0
  309. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_platforms_apple.py +0 -0
  310. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_presets_config.py +0 -0
  311. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_process_ipc.py +0 -0
  312. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_process_runs.py +0 -0
  313. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_protocols.py +0 -0
  314. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_python_app_tests_module.py +0 -0
  315. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_python_collection_chains.py +0 -0
  316. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_python_compat.py +0 -0
  317. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_python_entry_refs.py +0 -0
  318. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_python_fields.py +0 -0
  319. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_python_infer_cycles.py +0 -0
  320. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_python_roots.py +0 -0
  321. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_python_subprocess_tests.py +0 -0
  322. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_python_tests.py +0 -0
  323. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_python_web_hosts.py +0 -0
  324. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_python_web_routes.py +0 -0
  325. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_python_web_routes_more.py +0 -0
  326. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_react_router.py +0 -0
  327. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_realtime.py +0 -0
  328. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_realtime_native.py +0 -0
  329. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_request_keys.py +0 -0
  330. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_roundtrip.py +0 -0
  331. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_route_tables.py +0 -0
  332. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_routes_search_explain.py +0 -0
  333. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_rpc.py +0 -0
  334. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_scip_health.py +0 -0
  335. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_sdk_external.py +0 -0
  336. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_sdk_external_infra.py +0 -0
  337. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_sdk_external_mail.py +0 -0
  338. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_snippet.py +0 -0
  339. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_sockets.py +0 -0
  340. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_spring.py +0 -0
  341. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_ssrf.py +0 -0
  342. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_starters_budget.py +0 -0
  343. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_surface.py +0 -0
  344. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_surface_transport.py +0 -0
  345. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_swift.py +0 -0
  346. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_swift_binding.py +0 -0
  347. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_swift_exact.py +0 -0
  348. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_swift_facts.py +0 -0
  349. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_swift_fields.py +0 -0
  350. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_swift_modules.py +0 -0
  351. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_swift_more.py +0 -0
  352. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_swift_nav_values.py +0 -0
  353. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_swift_parse_errors.py +0 -0
  354. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_swift_props.py +0 -0
  355. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_swift_sdk.py +0 -0
  356. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_swift_testing.py +0 -0
  357. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_swift_values.py +0 -0
  358. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_tests_scope.py +0 -0
  359. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_ts_fields.py +0 -0
  360. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_ts_fields_js_vue.py +0 -0
  361. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_ts_file_specs.py +0 -0
  362. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_ts_frameworks.py +0 -0
  363. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_ts_node_http.py +0 -0
  364. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_ts_nuxt.py +0 -0
  365. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_ts_src_tsconfig.py +0 -0
  366. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_unguarded.py +0 -0
  367. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_values.py +0 -0
  368. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_viz.py +0 -0
  369. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_vue_nav.py +0 -0
  370. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_watch.py +0 -0
  371. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_webhooks.py +0 -0
  372. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_webhooks_152.py +0 -0
  373. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_webhooks_152b.py +0 -0
  374. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_websockets.py +0 -0
  375. {cg_code_graph-0.21.0 → cg_code_graph-0.21.1}/tests/test_workspace_link.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cg-code-graph
3
- Version: 0.21.0
3
+ Version: 0.21.1
4
4
  Summary: cg: a code graph of routes, calls, data access and platform boundaries for agents and humans (CLI + MCP server)
5
5
  Author: cyberchronos00
6
6
  License-Expression: MIT
@@ -1,2 +1,2 @@
1
1
  """code-graph: deterministic code knowledge graph (beta)."""
2
- __version__ = "0.21.0"
2
+ __version__ = "0.21.1"
@@ -1,7 +1,9 @@
1
1
  """Secret values never reach the graph database (#47).
2
2
 
3
- A literal that belongs to a credential-looking key (password, secret, token, key, api_key, auth, private, credential,
4
- passphrase, dsn, ...) is stored as `redacted:hmac:<first 8 hex of HMAC-SHA-256(graph salt, value)>`: enough to see that
3
+ A literal that belongs to a credential-looking key (its last word is password, secret, dsn, ..., or an
4
+ explicit compound such as api_key; a bare `key` / `token` counts unless a known non-secret word precedes it
5
+ (`primary_key`, `cache.key`), whatever the value looks like; `AUTH_GUARD` or `..._TOKEN_TABLE`
6
+ do not count) is stored as `redacted:hmac:<first 8 hex of HMAC-SHA-256(graph salt, value)>`: enough to see that
5
7
  a literal exists and to tell two values apart within one graph, not enough to recover one, and not recognisable by
6
8
  hashing a common password. The salt is `secrets.token_hex(16)`, created on the first index of a graph DB, kept in its
7
9
  `meta` table (`redact_salt`) and carried over by a re-index or refresh of that DB; a new DB gets a new salt, so markers
@@ -20,29 +22,52 @@ import secrets
20
22
 
21
23
  MARK = "redacted:hmac:"
22
24
  LEGACY_MARK = "redacted:sha256:"
23
- SECRET_WORDS = ("PASSWORD", "PASS", "PASSWD", "SECRET", "TOKEN", "SECRET_KEY", "SECRET_ACCESS_KEY", "KEY", "AUTH", "PWD")
24
- _EXTRA_WORDS = {"PASSWORD", "PASSWD", "PWD", "PASSPHRASE", "SECRET", "SECRETS", "TOKEN", "TOKENS", "AUTH", "AUTHORIZATION",
25
- "CREDENTIAL", "CREDENTIALS", "PRIVATE", "APIKEY", "DSN", "BEARER", "SALT", "SIGNATURE"}
26
- _NOT_SECRET_TAIL = ("_KEY_ID", "_PUBLIC_KEY", "_KEY_PATH")
25
+ _SECRET_LAST = {"password", "passwd", "pwd", "pass", "passphrase", "secret", "dsn"}
26
+ _SECRET_COMPOUNDS = {("api", "key"), ("apikey",), ("access", "key"), ("secret", "key"), ("private", "key"),
27
+ ("signing", "key"), ("encryption", "key"), ("client", "secret"), ("webhook", "secret"),
28
+ ("auth", "token"), ("api", "token"), ("access", "token"), ("refresh", "token"), ("bearer", "token")}
29
+ _BARE_LAST = {"key", "token"}
30
+ SECRET_WORDS = tuple(sorted({w.upper() for w in _SECRET_LAST} | {"_".join(c).upper() for c in _SECRET_COMPOUNDS}
31
+ | {w.upper() for w in _BARE_LAST}))
32
+ _NON_SECRET_BEFORE = {"primary", "foreign", "sort", "partition", "route", "cache", "idempotency", "remember", "csrf",
33
+ "xsrf", "public", "i18n", "translation", "lookup", "unique", "index", "storage", "prefix"}
27
34
  _URL_PW = re.compile(r"(?P<head>\b[A-Za-z][\w+.-]*://[^/\s:@'\"]*:)(?P<pw>[^@/\s'\"]+)(?P<tail>@)")
28
35
  _PLACEHOLDER = ("${", "{{", "%(", "<", "$")
29
36
 
30
37
 
31
- def secret_key(key: str) -> bool:
32
- """The `cg surface` rule for a config key / env name that holds a credential."""
33
- k = re.sub(r"[^A-Za-z0-9]+", "_", key).upper().strip("_")
34
- return any(k.endswith("_" + s) or k == s for s in SECRET_WORDS) and not k.endswith(_NOT_SECRET_TAIL)
35
-
36
-
37
- def looks_secret(key: str) -> bool:
38
- """Wider than `secret_key`: any word of the name says credential (private_key_pem, db_dsn, apiKey, auth_header)."""
39
- if secret_key(key):
38
+ def _words(segment: str) -> list[str]:
39
+ spaced = re.sub(r"([a-z])([A-Z])", r"\1_\2", segment)
40
+ return [w for w in re.split(r"[^A-Za-z0-9]+", spaced.lower()) if w]
41
+
42
+
43
+ def secret_key(key: str, value=None) -> bool:
44
+ """Whether a config key / env name holds a credential, from the words of the name (split on `.`, `_`, `-` and
45
+ camelCase). A credential when the last word is password, passwd, pwd, pass, passphrase, secret or dsn, when the
46
+ name ends in an explicit compound (api_key, access_key, signing_key, client_secret, auth_token, refresh_token, ...),
47
+ or for Laravel's `app.key` / `APP_KEY`. A bare `key` or `token` as last word is a credential by default, as it
48
+ was in 0.21.0, and is kept only when the word before it (a dotted segment counts) is a known non-secret one
49
+ (primary, foreign, sort, partition, route, cache, idempotency, remember, csrf, xsrf, public, i18n, translation,
50
+ lookup, unique, index, storage, prefix). The value never decides: a token can be any shape (lowercase words,
51
+ dotted, `key-` prefixed), so `value` is accepted for the callers' signature only. A credential word earlier in the name never counts
52
+ (`AUTH_GUARD`, `AUTH_PASSWORD_BROKER`, `AUTH_PASSWORD_RESET_TOKEN_TABLE`, `try_it_credentials_policy`), and
53
+ `*_PUBLIC_KEY`, `*_KEY_ID`, `*_KEY_PATH`, `*_KEY_FILE` are not credentials."""
54
+ key = str(key)
55
+ words = _words(key.rsplit(".", 1)[-1])
56
+ if not words:
57
+ return False
58
+ all_words = _words(key)
59
+ if all_words == ["app", "key"]:
40
60
  return True
41
- spaced = re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", str(key))
42
- words = [w for w in re.split(r"[^A-Za-z0-9]+", spaced.upper()) if w]
43
- if any(w in _EXTRA_WORDS for w in words):
61
+ if words[-1] in _SECRET_LAST or any(tuple(words[-n:]) in _SECRET_COMPOUNDS for n in (1, 2) if len(words) >= n):
44
62
  return True
45
- return "KEY" in words and not set(words) & {"PUBLIC", "ID", "PATH", "FILE", "NAME", "PREFIX", "TYPE", "SIZE", "LENGTH"}
63
+ if words[-1] not in _BARE_LAST:
64
+ return False
65
+ if len(all_words) > 1 and all_words[-2] in _NON_SECRET_BEFORE:
66
+ return False
67
+ return True
68
+
69
+
70
+ looks_secret = secret_key
46
71
 
47
72
 
48
73
  def is_redacted(v) -> bool:
@@ -79,7 +104,7 @@ def redact(value, key: str | None, salt: str):
79
104
  by one, anything else unchanged. Non-strings and placeholders pass through."""
80
105
  if not isinstance(value, str):
81
106
  return value
82
- if key is not None and looks_secret(key) and not placeholder(value):
107
+ if key is not None and looks_secret(key, value) and not placeholder(value):
83
108
  return marker(value, salt)
84
109
  return redact_url(value, salt)
85
110
 
@@ -100,7 +125,7 @@ def _holds_secret(d: dict, k: str) -> bool:
100
125
  if k.lower() in _DIRECT:
101
126
  return not _REFERENCE.match(str(d[k]))
102
127
  if k in _VALUE_KEYS:
103
- return any(isinstance(d.get(nk), str) and looks_secret(d[nk]) for nk in _NAME_KEYS)
128
+ return any(isinstance(d.get(nk), str) and looks_secret(d[nk], d.get(k)) for nk in _NAME_KEYS)
104
129
  return False
105
130
 
106
131
 
@@ -216,7 +216,7 @@ class LaravelPlugin(FrameworkPlugin):
216
216
  attrs["value"] = redact(n["literal"], n["key"], self.b.redact_salt)
217
217
  if n.get("envs"):
218
218
  attrs["env"] = [e["env"] for e in n["envs"]]
219
- attrs["env_default"] = [redact(e["default"], e["env"] if looks_secret(e["env"]) else n["key"], self.b.redact_salt)
219
+ attrs["env_default"] = [redact(e["default"], e["env"] if looks_secret(e["env"], e["default"]) else n["key"], self.b.redact_salt)
220
220
  for e in n["envs"]]
221
221
  cid = b.add_node("config", key, file=f, line=n["line"], module="config", lang="php", attrs=attrs)
222
222
  self.config_keys[key] = n
@@ -306,13 +306,13 @@ def _config_literals(ctx: Ctx) -> list[dict]:
306
306
  key = r["name"] or r["id"][len("config:"):]
307
307
  last = key.split(".")[-1]
308
308
  repo = ctx.repo_of(a, r["file"])
309
- if secret_key(last) and not _placeholder(a.get("value")):
309
+ if secret_key(last, a.get("value")) and not _placeholder(a.get("value")):
310
310
  out.append(make_finding(ctx, "hardcoded", protocol="config", node=r["id"], file=r["file"], line=r["line"],
311
311
  confidence="resolved", repo=repo, attrs=a, see=f"cg node '{r['id']}'",
312
312
  entry_ids=[r["id"]], detail=f"literal {_kind_of_key(last)} in config key {key} (value not shown)"))
313
313
  envs, defaults = a.get("env") or [], a.get("env_default") or []
314
314
  for env, dflt in zip(envs, defaults):
315
- if secret_key(str(env)) and not _placeholder(dflt):
315
+ if secret_key(str(env), dflt) and not _placeholder(dflt):
316
316
  out.append(make_finding(ctx, "hardcoded", protocol="config", node=r["id"], file=r["file"], line=r["line"],
317
317
  confidence="heuristic", repo=repo, attrs=a, see=f"cg node '{r['id']}'",
318
318
  entry_ids=[r["id"]], detail=f"literal default for env {env} in config key {key} (value not shown)"))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cg-code-graph
3
- Version: 0.21.0
3
+ Version: 0.21.1
4
4
  Summary: cg: a code graph of routes, calls, data access and platform boundaries for agents and humans (CLI + MCP server)
5
5
  Author: cyberchronos00
6
6
  License-Expression: MIT
@@ -0,0 +1,235 @@
1
+ """Salted secret fingerprints (#47 part 2d): `redacted:hmac:<8 hex>` is an HMAC-SHA-256 keyed with a per-graph salt kept
2
+ in the `meta` table (`redact_salt`), so a common password is not recognisable from its marker and markers only compare
3
+ within one graph (and across re-indexes of it)."""
4
+ import hashlib
5
+ import json
6
+ import shutil
7
+ import sqlite3
8
+ import sys
9
+ from pathlib import Path
10
+
11
+ import pytest
12
+
13
+ ROOT = Path(__file__).resolve().parents[1]
14
+ sys.path.insert(0, str(ROOT))
15
+ from cg_code_graph.core import redact as R # noqa: E402
16
+ from cg_code_graph.indexer import index_project # noqa: E402
17
+
18
+ PHP_FIX = ROOT / "tests" / "surface_fixture" / "php"
19
+ needs_php = pytest.mark.skipif(shutil.which("php") is None, reason="php is not installed (PHP extractor)")
20
+
21
+
22
+ def test_marker_is_keyed_not_a_plain_digest():
23
+ plain = hashlib.sha256(b"password").hexdigest()[:8]
24
+ assert plain == "5e884898"
25
+ m = R.marker("password", "salt-a-0000")
26
+ assert m.startswith(R.MARK) and m != R.MARK + plain and m != R.LEGACY_MARK + plain
27
+ assert plain not in m
28
+
29
+
30
+ def test_two_graphs_give_different_markers_and_one_graph_a_stable_one():
31
+ assert R.marker("hunter2", "salt-a") != R.marker("hunter2", "salt-b")
32
+ assert R.marker("hunter2", "salt-a") == R.marker("hunter2", "salt-a")
33
+ assert R.marker("hunter2", "salt-a") != R.marker("hunter3", "salt-a")
34
+ with pytest.raises(ValueError):
35
+ R.marker("hunter2", "")
36
+
37
+
38
+ def test_redact_and_urls_use_the_salt_and_both_prefixes_count_as_redacted():
39
+ assert R.redact("fake-bookstore-pw-0000", "db_password", "s1") == R.marker("fake-bookstore-pw-0000", "s1")
40
+ url = R.redact("mysql://reader:fake-bookstore-pw-0000@replica.example.test/shop", None, "s1")
41
+ assert url == f"mysql://reader:{R.marker('fake-bookstore-pw-0000', 's1')}@replica.example.test/shop"
42
+ assert R.is_redacted(R.marker("x", "s1")) and R.is_redacted("redacted:sha256:5e884898")
43
+ assert R.redact(R.marker("x", "s1"), "password", "s2") == R.marker("x", "s1") # a marker is never re-hashed
44
+
45
+
46
+ def _config(db):
47
+ con = sqlite3.connect(db)
48
+ try:
49
+ salt = json.loads(con.execute("SELECT value FROM meta WHERE key='redact_salt'").fetchone()[0])
50
+ attrs = {r[0]: json.loads(r[1] or "{}") for r in con.execute("SELECT id, attrs FROM nodes WHERE kind='config'")}
51
+ finally:
52
+ con.close()
53
+ return salt, attrs["config:services.github.secret"]["value"]
54
+
55
+
56
+ @needs_php
57
+ def test_salt_is_created_per_graph_and_kept_on_reindex(tmp_path):
58
+ a, b = tmp_path / "a.db", tmp_path / "b.db"
59
+ index_project(PHP_FIX, a, "php")
60
+ index_project(PHP_FIX, b, "php")
61
+ salt_a, marker_a = _config(a)
62
+ salt_b, marker_b = _config(b)
63
+ assert len(salt_a) == 32 and salt_a != salt_b
64
+ assert marker_a.startswith("redacted:hmac:") and marker_a != marker_b # two graphs, same value
65
+ index_project(PHP_FIX, a, "php") # re-index the same DB
66
+ assert _config(a) == (salt_a, marker_a)
67
+
68
+
69
+ @needs_php
70
+ def test_refresh_keeps_the_salt(tmp_path):
71
+ from cg_code_graph import hooks
72
+ root = tmp_path / "php"
73
+ shutil.copytree(PHP_FIX, root, ignore=shutil.ignore_patterns("vendor"))
74
+ db = tmp_path / "graph.db"
75
+ index_project(root, db, "php")
76
+ before = _config(db)
77
+ (root / "app" / "Services" / "Extra.php").write_text("<?php\nnamespace App\\Services;\nclass Extra {}\n")
78
+ assert hooks.refresh(str(root), str(db), "php", quiet=True) == 0
79
+ assert _config(db) == before
80
+
81
+
82
+ @needs_php
83
+ def test_cg_link_keeps_markers_and_has_no_salt_of_its_own(tmp_path):
84
+ from cg_code_graph.link import link_many
85
+ a, b, out = tmp_path / "a.db", tmp_path / "b.db", tmp_path / "combined.db"
86
+ index_project(PHP_FIX, a, "php-a")
87
+ index_project(PHP_FIX, b, "php-b")
88
+ link_many([("one", str(a), "both"), ("two", str(b), "both")], str(out))
89
+ con = sqlite3.connect(out)
90
+ try:
91
+ assert con.execute("SELECT 1 FROM meta WHERE key='redact_salt'").fetchone() is None
92
+ vals = {r[0]: json.loads(r[1] or "{}").get("value") for r in con.execute(
93
+ "SELECT id, attrs FROM nodes WHERE id LIKE '%config:services.github.secret'")}
94
+ finally:
95
+ con.close()
96
+ assert len(vals) == 2 and all(str(v).startswith("redacted:hmac:") for v in vals.values())
97
+ assert len(set(vals.values())) == 2 # fingerprints of different source graphs do not compare
98
+
99
+
100
+ LARAVEL_FIX = ROOT / "tests" / "redact_fixture" / "laravel-bookstore"
101
+
102
+
103
+ @pytest.mark.parametrize("key", ["AUTH_GUARD", "AUTH_PASSWORD_BROKER", "AUTH_PASSWORD_RESET_TOKEN_TABLE",
104
+ "try_it_credentials_policy", "auth.defaults.guard", "auth.passwords.readers.table",
105
+ "DB_PASSWORD_TABLE", "S3_PUBLIC_KEY", "SIGNING_KEY_ID", "SESSION_DRIVER", "tokenTtl",
106
+ "REPORTS_KEY_PATH", "primary_key", "foreign_key", "sort_key", "cache.key", "route_key",
107
+ "partition_key", "idempotency_key", "remember_token"])
108
+ def test_last_word_rule_leaves_framework_settings_alone(key):
109
+ assert not R.looks_secret(key, "created_at") and not R.secret_key(key, "created_at")
110
+
111
+
112
+ @pytest.mark.parametrize("key", ["AUTH_TOKEN", "DB_PASSWORD", "STRIPE_SECRET", "password", "client_secret", "api_key",
113
+ "apiKey", "REPORTS_DSN", "private_key", "signing_key", "ENCRYPTION_KEY",
114
+ "webhook_secret", "access_token", "refresh_token", "bearer_token", "DB_PASS",
115
+ "app.key", "APP_KEY", "STRIPE_SECRET_KEY"])
116
+ def test_last_word_rule_keeps_credentials(key):
117
+ assert R.looks_secret(key) and R.secret_key(key)
118
+
119
+
120
+ _HEX32 = "a" + ("fake" + "0a1b" * 7)[:31] # 32 chars, lowercase hex-looking, starts with a letter
121
+ _REDACTED_ROWS = [
122
+ ("LEDGER_TOKEN", "fake-bookstore-token-0000"),
123
+ ("LEDGER_TOKEN", "SURF-PHP-LEDGER-DEFAULT-d7e2"),
124
+ ("services.ledger.token", _HEX32),
125
+ ("MAILGUN_KEY", "key-" + "fake0a1b" * 3 + "fake0a"),
126
+ ("PUSHER_APP_KEY", "fakebookstore" + "abcdefghijk"[:9] + "0042"),
127
+ ("services.x.key", "FakeBook" + "Store12345" + "AbC"),
128
+ ]
129
+
130
+
131
+ @pytest.mark.parametrize("key,value", _REDACTED_ROWS)
132
+ def test_bare_key_and_token_with_credential_looking_values_are_redacted(key, value):
133
+ assert R.secret_key(key, value) and R.looks_secret(key, value)
134
+ assert R.redact(value, key, "s1").startswith(R.MARK)
135
+
136
+
137
+ _HOSTILE_ROWS = [
138
+ "key-abcdef", "key-fakebookstorekeynodigits", "key-FAKE", # key- prefixed, with and without digits
139
+ "abc.def.ghi", "fake.bookstore.token", # dotted, JWT-segment-like
140
+ "eyJmYWtlIjoiYm9va3N0b3JlIn0", "FakeBookstoreTokenNoDigits", # base64url segment, mixed case no digits
141
+ "fake_bookstore_token", "xoxb-fake-bookstore-token", "fakebookstore", # lowercase words only
142
+ ]
143
+
144
+
145
+ @pytest.mark.parametrize("key", ["services.ledger.token", "services.ledger.key", "LEDGER_TOKEN", "MAILGUN_KEY"])
146
+ @pytest.mark.parametrize("value", _HOSTILE_ROWS)
147
+ def test_bare_key_and_token_redact_any_value_shape(key, value):
148
+ assert R.secret_key(key, value)
149
+ assert R.redact(value, key, "s1").startswith(R.MARK)
150
+
151
+
152
+ @pytest.mark.parametrize("key", ["services.ledger.token", "services.ledger.key", "LEDGER_TOKEN", "STRIPE_KEY"])
153
+ def test_bare_key_and_token_are_redacted_whatever_the_value(key):
154
+ assert R.secret_key(key) and R.secret_key(key, None) and R.secret_key(key, 12345) # no value: redact
155
+ assert R.secret_key(key, "sk_test_FAKE_bookstore_000000")
156
+ assert R.secret_key(key, "sk_fakebookstore") and R.secret_key(key, "pk_live_fakebookstore")
157
+ assert R.secret_key(key, "rk-fakebookstore")
158
+ assert R.secret_key(key, "base64:FAKEBOOKSTOREAPPKEY0000000000000000000000=")
159
+ assert R.secret_key(key, "Remember_Token") and R.secret_key(key, "token1")
160
+ assert R.secret_key(key, "a" * 41) and R.secret_key(key, R.marker("x", "s1"))
161
+ assert R.secret_key(key, "a" * 40)
162
+ assert R.secret_key(key, "created_at") and R.secret_key(key, "x-idempotency-key")
163
+
164
+
165
+ @pytest.mark.parametrize("key,value", [("primary_key", "id"), ("foreign_key", "author_id"), ("sort_key", "created_at"),
166
+ ("remember_token", "remember_token"), ("cache.key", "bookstore_cache"),
167
+ ("idempotency_key", "x-idempotency-key"), ("AUTH_GUARD", "web"),
168
+ ("AUTH_PASSWORD_BROKER", "readers"),
169
+ ("AUTH_PASSWORD_RESET_TOKEN_TABLE", "reader_password_resets"),
170
+ ("try_it_credentials_policy", "include")])
171
+ def test_kept_cases(key, value):
172
+ assert not R.secret_key(key, value)
173
+ assert R.redact(value, key, "s1") == value
174
+
175
+
176
+ @pytest.mark.parametrize("word", ["primary", "foreign", "sort", "partition", "route", "cache", "idempotency",
177
+ "remember", "csrf", "xsrf", "public", "i18n", "translation", "lookup", "unique",
178
+ "index", "storage", "prefix"])
179
+ @pytest.mark.parametrize("last", ["key", "token"])
180
+ def test_known_non_secret_compounds_keep_any_value(word, last):
181
+ assert not R.secret_key(f"{word}_{last}", "Fake0a1b" * 4)
182
+ assert not R.secret_key(f"{word.upper()}_{last.upper()}", "Fake0a1b" * 4)
183
+ assert not R.secret_key(f"app.{word}.{last}", "Fake0a1b" * 4)
184
+
185
+
186
+ @pytest.mark.parametrize("key", ["S3_KEY_ID", "S3_PUBLIC_KEY", "SIGNING_KEY_PATH", "SIGNING_KEY_FILE"])
187
+ def test_key_id_public_key_and_path_are_never_credentials(key):
188
+ assert not R.secret_key(key, "Fake0a1b" * 4)
189
+
190
+
191
+ def test_redact_keeps_a_guard_name_and_hides_a_password():
192
+ assert R.redact("web", "guard", "s1") == "web"
193
+ assert R.redact("readers", "AUTH_PASSWORD_BROKER", "s1") == "readers"
194
+ assert R.redact("fake-bookstore-pw-0000", "DB_PASSWORD", "s1").startswith(R.MARK)
195
+
196
+
197
+ @needs_php
198
+ def test_laravel_bookstore_config_keeps_defaults_and_redacts_secrets(tmp_path):
199
+ db = tmp_path / "laravel.db"
200
+ index_project(LARAVEL_FIX, db, "laravel-bookstore")
201
+ con = sqlite3.connect(db)
202
+ try:
203
+ attrs = {r[0]: json.loads(r[1] or "{}") for r in con.execute("SELECT id, attrs FROM nodes WHERE kind='config'")}
204
+ finally:
205
+ con.close()
206
+ assert attrs["config:auth.defaults.guard"]["env_default"] == ["web"]
207
+ assert attrs["config:auth.defaults.passwords"]["env_default"] == ["readers"]
208
+ assert attrs["config:auth.passwords.readers.table"]["env_default"] == ["reader_password_resets"]
209
+ assert attrs["config:shelfdocs.try_it_credentials_policy"]["value"] == "include"
210
+ assert attrs["config:models.primary_key"]["value"] == "id"
211
+ assert attrs["config:models.foreign_key"]["value"] == "author_id"
212
+ assert attrs["config:models.sort_key"]["value"] == "created_at"
213
+ assert attrs["config:models.remember_token"]["value"] == "remember_token"
214
+ assert attrs["config:models.cache.key"]["value"] == "bookstore_cache"
215
+ assert attrs["config:services.ledger.idempotency_key"]["value"] == "x-idempotency-key"
216
+ redacted = ["config:database.connections.pgsql.password", "config:services.ledger.token", "config:app.key",
217
+ "config:services.stripe.secret"]
218
+ for nid in redacted:
219
+ assert attrs[nid]["env_default"][0].startswith(R.MARK), nid
220
+ assert attrs["config:services.ledger.key"]["value"].startswith(R.MARK)
221
+ assert attrs["config:shelfdocs.client_secret"]["value"].startswith(R.MARK)
222
+ assert "fake-bookstore" not in json.dumps(attrs) and "FAKE" not in json.dumps(attrs)
223
+
224
+
225
+ @needs_php
226
+ def test_surface_php_fixture_still_redacts_exactly_three_values(tmp_path):
227
+ db = tmp_path / "php.db"
228
+ index_project(PHP_FIX, db, "php")
229
+ con = sqlite3.connect(db)
230
+ try:
231
+ attrs = [json.loads(r[0] or "{}") for r in con.execute("SELECT attrs FROM nodes WHERE kind='config'")]
232
+ finally:
233
+ con.close()
234
+ n = sum(1 for a in attrs for v in [a.get("value"), *(a.get("env_default") or [])] if R.is_redacted(v))
235
+ assert n == 3
@@ -1,97 +0,0 @@
1
- """Salted secret fingerprints (#47 part 2d): `redacted:hmac:<8 hex>` is an HMAC-SHA-256 keyed with a per-graph salt kept
2
- in the `meta` table (`redact_salt`), so a common password is not recognisable from its marker and markers only compare
3
- within one graph (and across re-indexes of it)."""
4
- import hashlib
5
- import json
6
- import shutil
7
- import sqlite3
8
- import sys
9
- from pathlib import Path
10
-
11
- import pytest
12
-
13
- ROOT = Path(__file__).resolve().parents[1]
14
- sys.path.insert(0, str(ROOT))
15
- from cg_code_graph.core import redact as R # noqa: E402
16
- from cg_code_graph.indexer import index_project # noqa: E402
17
-
18
- PHP_FIX = ROOT / "tests" / "surface_fixture" / "php"
19
- needs_php = pytest.mark.skipif(shutil.which("php") is None, reason="php is not installed (PHP extractor)")
20
-
21
-
22
- def test_marker_is_keyed_not_a_plain_digest():
23
- plain = hashlib.sha256(b"password").hexdigest()[:8]
24
- assert plain == "5e884898"
25
- m = R.marker("password", "salt-a-0000")
26
- assert m.startswith(R.MARK) and m != R.MARK + plain and m != R.LEGACY_MARK + plain
27
- assert plain not in m
28
-
29
-
30
- def test_two_graphs_give_different_markers_and_one_graph_a_stable_one():
31
- assert R.marker("hunter2", "salt-a") != R.marker("hunter2", "salt-b")
32
- assert R.marker("hunter2", "salt-a") == R.marker("hunter2", "salt-a")
33
- assert R.marker("hunter2", "salt-a") != R.marker("hunter3", "salt-a")
34
- with pytest.raises(ValueError):
35
- R.marker("hunter2", "")
36
-
37
-
38
- def test_redact_and_urls_use_the_salt_and_both_prefixes_count_as_redacted():
39
- assert R.redact("fake-bookstore-pw-0000", "db_password", "s1") == R.marker("fake-bookstore-pw-0000", "s1")
40
- url = R.redact("mysql://reader:fake-bookstore-pw-0000@replica.example.test/shop", None, "s1")
41
- assert url == f"mysql://reader:{R.marker('fake-bookstore-pw-0000', 's1')}@replica.example.test/shop"
42
- assert R.is_redacted(R.marker("x", "s1")) and R.is_redacted("redacted:sha256:5e884898")
43
- assert R.redact(R.marker("x", "s1"), "password", "s2") == R.marker("x", "s1") # a marker is never re-hashed
44
-
45
-
46
- def _config(db):
47
- con = sqlite3.connect(db)
48
- try:
49
- salt = json.loads(con.execute("SELECT value FROM meta WHERE key='redact_salt'").fetchone()[0])
50
- attrs = {r[0]: json.loads(r[1] or "{}") for r in con.execute("SELECT id, attrs FROM nodes WHERE kind='config'")}
51
- finally:
52
- con.close()
53
- return salt, attrs["config:services.github.secret"]["value"]
54
-
55
-
56
- @needs_php
57
- def test_salt_is_created_per_graph_and_kept_on_reindex(tmp_path):
58
- a, b = tmp_path / "a.db", tmp_path / "b.db"
59
- index_project(PHP_FIX, a, "php")
60
- index_project(PHP_FIX, b, "php")
61
- salt_a, marker_a = _config(a)
62
- salt_b, marker_b = _config(b)
63
- assert len(salt_a) == 32 and salt_a != salt_b
64
- assert marker_a.startswith("redacted:hmac:") and marker_a != marker_b # two graphs, same value
65
- index_project(PHP_FIX, a, "php") # re-index the same DB
66
- assert _config(a) == (salt_a, marker_a)
67
-
68
-
69
- @needs_php
70
- def test_refresh_keeps_the_salt(tmp_path):
71
- from cg_code_graph import hooks
72
- root = tmp_path / "php"
73
- shutil.copytree(PHP_FIX, root, ignore=shutil.ignore_patterns("vendor"))
74
- db = tmp_path / "graph.db"
75
- index_project(root, db, "php")
76
- before = _config(db)
77
- (root / "app" / "Services" / "Extra.php").write_text("<?php\nnamespace App\\Services;\nclass Extra {}\n")
78
- assert hooks.refresh(str(root), str(db), "php", quiet=True) == 0
79
- assert _config(db) == before
80
-
81
-
82
- @needs_php
83
- def test_cg_link_keeps_markers_and_has_no_salt_of_its_own(tmp_path):
84
- from cg_code_graph.link import link_many
85
- a, b, out = tmp_path / "a.db", tmp_path / "b.db", tmp_path / "combined.db"
86
- index_project(PHP_FIX, a, "php-a")
87
- index_project(PHP_FIX, b, "php-b")
88
- link_many([("one", str(a), "both"), ("two", str(b), "both")], str(out))
89
- con = sqlite3.connect(out)
90
- try:
91
- assert con.execute("SELECT 1 FROM meta WHERE key='redact_salt'").fetchone() is None
92
- vals = {r[0]: json.loads(r[1] or "{}").get("value") for r in con.execute(
93
- "SELECT id, attrs FROM nodes WHERE id LIKE '%config:services.github.secret'")}
94
- finally:
95
- con.close()
96
- assert len(vals) == 2 and all(str(v).startswith("redacted:hmac:") for v in vals.values())
97
- assert len(set(vals.values())) == 2 # fingerprints of different source graphs do not compare
File without changes
File without changes