configmanbearpig 2.0.0__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 (532) hide show
  1. configmanbearpig-2.0.0/.agents/skills/grill-me/SKILL.md +20 -0
  2. configmanbearpig-2.0.0/.agents/skills/openhound/SKILL.md +46 -0
  3. configmanbearpig-2.0.0/.agents/skills/openhound/references/add-asset.md +177 -0
  4. configmanbearpig-2.0.0/.agents/skills/openhound/references/graph-schema.md +114 -0
  5. configmanbearpig-2.0.0/.agents/skills/openhound/references/plan-collector.md +120 -0
  6. configmanbearpig-2.0.0/.agents/skills/openhound/references/preproc-lookup.md +154 -0
  7. configmanbearpig-2.0.0/.agents/skills/openhound/references/register-extension.md +132 -0
  8. configmanbearpig-2.0.0/.agents/skills/openhound/references/source-collection.md +119 -0
  9. configmanbearpig-2.0.0/.agents/skills/openhound/references/validate-extension.md +70 -0
  10. configmanbearpig-2.0.0/.agents/standards/openhound.md +62 -0
  11. configmanbearpig-2.0.0/.agents/standards/workflow.md +39 -0
  12. configmanbearpig-2.0.0/.gitattributes +15 -0
  13. configmanbearpig-2.0.0/.github/workflows/ci.yml +42 -0
  14. configmanbearpig-2.0.0/.github/workflows/release.yml +101 -0
  15. configmanbearpig-2.0.0/.gitignore +241 -0
  16. configmanbearpig-2.0.0/.pre-commit-config.yaml +13 -0
  17. configmanbearpig-2.0.0/.tickets/Ope-0t3h.md +24 -0
  18. configmanbearpig-2.0.0/.tickets/Ope-15m7.md +110 -0
  19. configmanbearpig-2.0.0/.tickets/Ope-4tdt.md +44 -0
  20. configmanbearpig-2.0.0/.tickets/Ope-6cei.md +24 -0
  21. configmanbearpig-2.0.0/.tickets/Ope-8wi2.md +37 -0
  22. configmanbearpig-2.0.0/.tickets/Ope-bmyk.md +29 -0
  23. configmanbearpig-2.0.0/.tickets/Ope-emhc.md +29 -0
  24. configmanbearpig-2.0.0/.tickets/Ope-ew5k.md +29 -0
  25. configmanbearpig-2.0.0/.tickets/Ope-exvi.md +23 -0
  26. configmanbearpig-2.0.0/.tickets/Ope-f3di.md +59 -0
  27. configmanbearpig-2.0.0/.tickets/Ope-gqwo.md +23 -0
  28. configmanbearpig-2.0.0/.tickets/Ope-l6fu.md +24 -0
  29. configmanbearpig-2.0.0/.tickets/Ope-liu7.md +29 -0
  30. configmanbearpig-2.0.0/.tickets/Ope-o008.md +29 -0
  31. configmanbearpig-2.0.0/.tickets/Ope-o6bh.md +24 -0
  32. configmanbearpig-2.0.0/.tickets/Ope-padv.md +23 -0
  33. configmanbearpig-2.0.0/.tickets/Ope-pofz.md +18 -0
  34. configmanbearpig-2.0.0/.tickets/Ope-rhzx.md +33 -0
  35. configmanbearpig-2.0.0/.tickets/Ope-scp1.md +39 -0
  36. configmanbearpig-2.0.0/.tickets/Ope-t7kv.md +33 -0
  37. configmanbearpig-2.0.0/.tickets/Ope-txs0.md +24 -0
  38. configmanbearpig-2.0.0/.tickets/Ope-vpdw.md +18 -0
  39. configmanbearpig-2.0.0/.tickets/Ope-zaja.md +24 -0
  40. configmanbearpig-2.0.0/.tickets/_TICKETS-BY-STATUS.md +170 -0
  41. configmanbearpig-2.0.0/.tickets/con-0170.md +24 -0
  42. configmanbearpig-2.0.0/.tickets/con-0289.md +30 -0
  43. configmanbearpig-2.0.0/.tickets/con-0394.md +44 -0
  44. configmanbearpig-2.0.0/.tickets/con-2249.md +24 -0
  45. configmanbearpig-2.0.0/.tickets/con-2ca2.md +43 -0
  46. configmanbearpig-2.0.0/.tickets/con-3354.md +63 -0
  47. configmanbearpig-2.0.0/.tickets/con-3be4.md +28 -0
  48. configmanbearpig-2.0.0/.tickets/con-401c.md +32 -0
  49. configmanbearpig-2.0.0/.tickets/con-53eb.md +30 -0
  50. configmanbearpig-2.0.0/.tickets/con-5e71.md +27 -0
  51. configmanbearpig-2.0.0/.tickets/con-6198.md +30 -0
  52. configmanbearpig-2.0.0/.tickets/con-6677.md +28 -0
  53. configmanbearpig-2.0.0/.tickets/con-68c2.md +33 -0
  54. configmanbearpig-2.0.0/.tickets/con-727a.md +40 -0
  55. configmanbearpig-2.0.0/.tickets/con-7296.md +19 -0
  56. configmanbearpig-2.0.0/.tickets/con-7741.md +27 -0
  57. configmanbearpig-2.0.0/.tickets/con-7842.md +22 -0
  58. configmanbearpig-2.0.0/.tickets/con-894a.md +22 -0
  59. configmanbearpig-2.0.0/.tickets/con-8a28.md +45 -0
  60. configmanbearpig-2.0.0/.tickets/con-8a33.md +25 -0
  61. configmanbearpig-2.0.0/.tickets/con-907c.md +54 -0
  62. configmanbearpig-2.0.0/.tickets/con-a4ec.md +42 -0
  63. configmanbearpig-2.0.0/.tickets/con-ab59.md +63 -0
  64. configmanbearpig-2.0.0/.tickets/con-acdd.md +27 -0
  65. configmanbearpig-2.0.0/.tickets/con-be15.md +66 -0
  66. configmanbearpig-2.0.0/.tickets/con-be32.md +23 -0
  67. configmanbearpig-2.0.0/.tickets/con-c509.md +46 -0
  68. configmanbearpig-2.0.0/.tickets/con-c522.md +28 -0
  69. configmanbearpig-2.0.0/.tickets/con-c542.md +28 -0
  70. configmanbearpig-2.0.0/.tickets/con-d061.md +26 -0
  71. configmanbearpig-2.0.0/.tickets/con-d857.md +11 -0
  72. configmanbearpig-2.0.0/.tickets/con-e455.md +32 -0
  73. configmanbearpig-2.0.0/.tickets/con-edee.md +27 -0
  74. configmanbearpig-2.0.0/.tickets/ope-00ca.md +20 -0
  75. configmanbearpig-2.0.0/.tickets/ope-00df.md +13 -0
  76. configmanbearpig-2.0.0/.tickets/ope-0112.md +17 -0
  77. configmanbearpig-2.0.0/.tickets/ope-0495.md +31 -0
  78. configmanbearpig-2.0.0/.tickets/ope-065f.md +16 -0
  79. configmanbearpig-2.0.0/.tickets/ope-0947.md +62 -0
  80. configmanbearpig-2.0.0/.tickets/ope-0f66.md +14 -0
  81. configmanbearpig-2.0.0/.tickets/ope-1172.md +11 -0
  82. configmanbearpig-2.0.0/.tickets/ope-1201.md +20 -0
  83. configmanbearpig-2.0.0/.tickets/ope-140f.md +13 -0
  84. configmanbearpig-2.0.0/.tickets/ope-16f5.md +24 -0
  85. configmanbearpig-2.0.0/.tickets/ope-194a.md +13 -0
  86. configmanbearpig-2.0.0/.tickets/ope-1950.md +21 -0
  87. configmanbearpig-2.0.0/.tickets/ope-1d06.md +18 -0
  88. configmanbearpig-2.0.0/.tickets/ope-1f0f.md +68 -0
  89. configmanbearpig-2.0.0/.tickets/ope-1f49.md +76 -0
  90. configmanbearpig-2.0.0/.tickets/ope-215a.md +17 -0
  91. configmanbearpig-2.0.0/.tickets/ope-2419.md +18 -0
  92. configmanbearpig-2.0.0/.tickets/ope-255b.md +15 -0
  93. configmanbearpig-2.0.0/.tickets/ope-272e.md +21 -0
  94. configmanbearpig-2.0.0/.tickets/ope-272f.md +26 -0
  95. configmanbearpig-2.0.0/.tickets/ope-2732.md +24 -0
  96. configmanbearpig-2.0.0/.tickets/ope-2f15.md +20 -0
  97. configmanbearpig-2.0.0/.tickets/ope-2ff3.md +15 -0
  98. configmanbearpig-2.0.0/.tickets/ope-334f.md +21 -0
  99. configmanbearpig-2.0.0/.tickets/ope-38ad.md +21 -0
  100. configmanbearpig-2.0.0/.tickets/ope-3d28.md +21 -0
  101. configmanbearpig-2.0.0/.tickets/ope-3dbc.md +20 -0
  102. configmanbearpig-2.0.0/.tickets/ope-3de2.md +13 -0
  103. configmanbearpig-2.0.0/.tickets/ope-3f2a.md +21 -0
  104. configmanbearpig-2.0.0/.tickets/ope-4483.md +33 -0
  105. configmanbearpig-2.0.0/.tickets/ope-46ef.md +14 -0
  106. configmanbearpig-2.0.0/.tickets/ope-4787.md +11 -0
  107. configmanbearpig-2.0.0/.tickets/ope-4ba1.md +20 -0
  108. configmanbearpig-2.0.0/.tickets/ope-4c6f.md +18 -0
  109. configmanbearpig-2.0.0/.tickets/ope-50cc.md +18 -0
  110. configmanbearpig-2.0.0/.tickets/ope-5186.md +20 -0
  111. configmanbearpig-2.0.0/.tickets/ope-5271.md +25 -0
  112. configmanbearpig-2.0.0/.tickets/ope-54be.md +27 -0
  113. configmanbearpig-2.0.0/.tickets/ope-57cf.md +13 -0
  114. configmanbearpig-2.0.0/.tickets/ope-60fe.md +73 -0
  115. configmanbearpig-2.0.0/.tickets/ope-6569.md +20 -0
  116. configmanbearpig-2.0.0/.tickets/ope-6716.md +24 -0
  117. configmanbearpig-2.0.0/.tickets/ope-676f.md +17 -0
  118. configmanbearpig-2.0.0/.tickets/ope-6aa7.md +15 -0
  119. configmanbearpig-2.0.0/.tickets/ope-6b93.md +20 -0
  120. configmanbearpig-2.0.0/.tickets/ope-7313.md +21 -0
  121. configmanbearpig-2.0.0/.tickets/ope-76f1.md +23 -0
  122. configmanbearpig-2.0.0/.tickets/ope-7da1.md +20 -0
  123. configmanbearpig-2.0.0/.tickets/ope-7e54.md +70 -0
  124. configmanbearpig-2.0.0/.tickets/ope-7f61.md +14 -0
  125. configmanbearpig-2.0.0/.tickets/ope-86f8.md +13 -0
  126. configmanbearpig-2.0.0/.tickets/ope-8b99.md +23 -0
  127. configmanbearpig-2.0.0/.tickets/ope-8c44.md +24 -0
  128. configmanbearpig-2.0.0/.tickets/ope-90fc.md +15 -0
  129. configmanbearpig-2.0.0/.tickets/ope-9271.md +29 -0
  130. configmanbearpig-2.0.0/.tickets/ope-961c.md +18 -0
  131. configmanbearpig-2.0.0/.tickets/ope-9989.md +28 -0
  132. configmanbearpig-2.0.0/.tickets/ope-9d62.md +11 -0
  133. configmanbearpig-2.0.0/.tickets/ope-a214.md +24 -0
  134. configmanbearpig-2.0.0/.tickets/ope-a88e.md +21 -0
  135. configmanbearpig-2.0.0/.tickets/ope-aa39.md +60 -0
  136. configmanbearpig-2.0.0/.tickets/ope-ad1c.md +12 -0
  137. configmanbearpig-2.0.0/.tickets/ope-afc8.md +25 -0
  138. configmanbearpig-2.0.0/.tickets/ope-b1e8.md +20 -0
  139. configmanbearpig-2.0.0/.tickets/ope-b287.md +17 -0
  140. configmanbearpig-2.0.0/.tickets/ope-b7b2.md +24 -0
  141. configmanbearpig-2.0.0/.tickets/ope-b916.md +36 -0
  142. configmanbearpig-2.0.0/.tickets/ope-c0c0.md +20 -0
  143. configmanbearpig-2.0.0/.tickets/ope-c141.md +20 -0
  144. configmanbearpig-2.0.0/.tickets/ope-c660.md +17 -0
  145. configmanbearpig-2.0.0/.tickets/ope-c8cc.md +26 -0
  146. configmanbearpig-2.0.0/.tickets/ope-c8dd.md +14 -0
  147. configmanbearpig-2.0.0/.tickets/ope-cc0f.md +24 -0
  148. configmanbearpig-2.0.0/.tickets/ope-d57d.md +28 -0
  149. configmanbearpig-2.0.0/.tickets/ope-d820.md +15 -0
  150. configmanbearpig-2.0.0/.tickets/ope-da2a.md +19 -0
  151. configmanbearpig-2.0.0/.tickets/ope-df0e.md +13 -0
  152. configmanbearpig-2.0.0/.tickets/ope-e10b.md +14 -0
  153. configmanbearpig-2.0.0/.tickets/ope-e191.md +38 -0
  154. configmanbearpig-2.0.0/.tickets/ope-e512.md +17 -0
  155. configmanbearpig-2.0.0/.tickets/ope-e739.md +28 -0
  156. configmanbearpig-2.0.0/.tickets/ope-ec50.md +13 -0
  157. configmanbearpig-2.0.0/.tickets/ope-f173.md +17 -0
  158. configmanbearpig-2.0.0/.tickets/ope-f1ce.md +18 -0
  159. configmanbearpig-2.0.0/.tickets/ope-f27c.md +19 -0
  160. configmanbearpig-2.0.0/.tickets/ope-f651.md +18 -0
  161. configmanbearpig-2.0.0/.tickets/ope-fb99.md +20 -0
  162. configmanbearpig-2.0.0/.tickets/ope-fbb0.md +20 -0
  163. configmanbearpig-2.0.0/.tickets/ope-feb0.md +24 -0
  164. configmanbearpig-2.0.0/.tickets/ope-ff28.md +14 -0
  165. configmanbearpig-2.0.0/AGENTS.md +210 -0
  166. configmanbearpig-2.0.0/ARCHITECTURE.md +2090 -0
  167. configmanbearpig-2.0.0/CLAUDE.md +69 -0
  168. configmanbearpig-2.0.0/LICENSE +201 -0
  169. configmanbearpig-2.0.0/PKG-INFO +2499 -0
  170. configmanbearpig-2.0.0/README.md +2471 -0
  171. configmanbearpig-2.0.0/cypher_queries/SCCM Admin Logon Sessions.json +1 -0
  172. configmanbearpig-2.0.0/cypher_queries/SCCM Admin Users.json +1 -0
  173. configmanbearpig-2.0.0/cypher_queries/SCCM Admins Who Can Escalate Other Admins.json +1 -0
  174. configmanbearpig-2.0.0/cypher_queries/SCCM CRED-3.json +1 -0
  175. configmanbearpig-2.0.0/cypher_queries/SCCM CRED-5.json +1 -0
  176. configmanbearpig-2.0.0/cypher_queries/SCCM Client Device Users.json +1 -0
  177. configmanbearpig-2.0.0/cypher_queries/SCCM ELEVATE-1.json +1 -0
  178. configmanbearpig-2.0.0/cypher_queries/SCCM Hierarchy TAKEOVER-1.json +1 -0
  179. configmanbearpig-2.0.0/cypher_queries/SCCM Hierarchy TAKEOVER-2.json +1 -0
  180. configmanbearpig-2.0.0/cypher_queries/SCCM Hierarchy TAKEOVER-3.json +1 -0
  181. configmanbearpig-2.0.0/cypher_queries/SCCM Hierarchy TAKEOVER-4.json +1 -0
  182. configmanbearpig-2.0.0/cypher_queries/SCCM Hierarchy TAKEOVER-5.json +1 -0
  183. configmanbearpig-2.0.0/cypher_queries/SCCM Hierarchy TAKEOVER-6.json +1 -0
  184. configmanbearpig-2.0.0/cypher_queries/SCCM Hierarchy TAKEOVER-7.json +1 -0
  185. configmanbearpig-2.0.0/cypher_queries/SCCM Hierarchy TAKEOVER-8.json +1 -0
  186. configmanbearpig-2.0.0/cypher_queries/SCCM Hierarchy TAKEOVER-9.json +1 -0
  187. configmanbearpig-2.0.0/cypher_queries/SCCM Hierarchy TAKEOVERs.json +1 -0
  188. configmanbearpig-2.0.0/cypher_queries/SCCM Infrastructure Logons.json +1 -0
  189. configmanbearpig-2.0.0/cypher_queries/SCCM Infrastructure.json +1 -0
  190. configmanbearpig-2.0.0/cypher_queries/SCCM Principals with Full Control of System Management Container (Possible Site Servers).json +1 -0
  191. configmanbearpig-2.0.0/cypher_queries/SCCM Shortest TAKEOVER Path.json +1 -0
  192. configmanbearpig-2.0.0/cypher_queries/SCCM Site Database Service Account to Client Device.json +1 -0
  193. configmanbearpig-2.0.0/cypher_queries/SCCM Site Server Has Local Admin on Site System Roles.json +1 -0
  194. configmanbearpig-2.0.0/cypher_queries/SCCM Sites.json +1 -0
  195. configmanbearpig-2.0.0/dev/_ab_cmbp.py +47 -0
  196. configmanbearpig-2.0.0/dev/ab_matrix.py +187 -0
  197. configmanbearpig-2.0.0/dev/debug_epa_matrix.py +613 -0
  198. configmanbearpig-2.0.0/dev/debug_per_host.py +192 -0
  199. configmanbearpig-2.0.0/dev/debug_smb_auth.py +178 -0
  200. configmanbearpig-2.0.0/dev/debug_wmi_auth.py +166 -0
  201. configmanbearpig-2.0.0/dev/regen_ticket_index.py +155 -0
  202. configmanbearpig-2.0.0/dev/spike_smb_sso.py +149 -0
  203. configmanbearpig-2.0.0/dev/spike_socks_proxy.md +179 -0
  204. configmanbearpig-2.0.0/dev/tour_driver_stage0.py +24 -0
  205. configmanbearpig-2.0.0/dev/tour_driver_stage1.py +106 -0
  206. configmanbearpig-2.0.0/dev/tour_driver_stage2.py +152 -0
  207. configmanbearpig-2.0.0/dev/tour_driver_stage3.py +401 -0
  208. configmanbearpig-2.0.0/docs/PUBLISHING.md +771 -0
  209. configmanbearpig-2.0.0/docs/per-host-collection-framework-tour.md +314 -0
  210. configmanbearpig-2.0.0/docs/proposals/2026-06-16-computer-node-multi-driver-merge.md +322 -0
  211. configmanbearpig-2.0.0/docs/proposals/2026-06-16-convert-read-from-duckdb.md +314 -0
  212. configmanbearpig-2.0.0/docs/superpowers/plans/2026-05-26-ldap-management-points-raw.md +822 -0
  213. configmanbearpig-2.0.0/docs/superpowers/plans/2026-05-29-dns-resolver-flag.md +535 -0
  214. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-03-per-host-collection-framework.md +377 -0
  215. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-04-impacket-sspi-smb-sso.md +850 -0
  216. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-09-sccm-adminservice-collector.md +1025 -0
  217. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-09-sccm-http-client.md +1269 -0
  218. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-11-sccm-wmi-fallback-collector.md +518 -0
  219. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-12-merge-privileged-collectors.md +805 -0
  220. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-15-sccm-http-collector.md +271 -0
  221. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-16-sccm-preproc-convert-stage0-validation.md +118 -0
  222. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-16-sccm-preproc-convert-stage0.md +636 -0
  223. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-17-sccm-preproc-convert-stage1-validation.md +215 -0
  224. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-17-sccm-preproc-convert-stage1.md +826 -0
  225. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-23-sccm-preproc-convert-stage2-validation.md +85 -0
  226. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-23-sccm-preproc-convert-stage2.md +965 -0
  227. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-24-sccm-preproc-convert-stage3-validation.md +368 -0
  228. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-24-sccm-preproc-convert-stage3.md +935 -0
  229. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-24-stage3-property-matrix.md +249 -0
  230. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-26-sccm-cmbp-property-casing.md +242 -0
  231. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-29-collect-summary-per-run-metric.md +503 -0
  232. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-29-sccm-preproc-convert-stage4-validation.md +323 -0
  233. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-29-sccm-preproc-convert-stage4.md +930 -0
  234. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-29-sccm-preproc-convert-stage5-validation.md +608 -0
  235. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-29-sccm-preproc-convert-stage5.md +1964 -0
  236. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-29-split-ad-nodes-edges-output.md +786 -0
  237. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-30-sccm-preproc-convert-stage6-validation.md +640 -0
  238. configmanbearpig-2.0.0/docs/superpowers/plans/2026-06-30-sccm-preproc-convert-stage6.md +1273 -0
  239. configmanbearpig-2.0.0/docs/superpowers/plans/2026-07-01-sccm-preproc-convert-stage7-validation.md +195 -0
  240. configmanbearpig-2.0.0/docs/superpowers/plans/2026-07-01-sccm-preproc-convert-stage7.md +567 -0
  241. configmanbearpig-2.0.0/docs/superpowers/plans/2026-07-15-edge-entity-panel-help.md +629 -0
  242. configmanbearpig-2.0.0/docs/superpowers/plans/2026-07-16-openhound-run-all-shared-orchestrator.md +748 -0
  243. configmanbearpig-2.0.0/docs/superpowers/plans/2026-07-17-sccm-version-cve-fingerprint.md +693 -0
  244. configmanbearpig-2.0.0/docs/superpowers/plans/2026-07-17-socks5-proxy-all-collection-traffic.md +1137 -0
  245. configmanbearpig-2.0.0/docs/superpowers/plans/2026-07-21-ope-b7b2-ldap-pth-ptt-and-mssql-ticket-warning.md +436 -0
  246. configmanbearpig-2.0.0/docs/superpowers/plans/2026-07-21-tier1-tier2-smc-abuse-and-cleanup.md +227 -0
  247. configmanbearpig-2.0.0/docs/superpowers/plans/2026-07-22-dc-only-flag.md +416 -0
  248. configmanbearpig-2.0.0/docs/superpowers/plans/2026-07-22-sccm-integration-test-kit.md +1576 -0
  249. configmanbearpig-2.0.0/docs/superpowers/plans/2026-07-23-cmbp-parity-node-edge-properties.md +413 -0
  250. configmanbearpig-2.0.0/docs/superpowers/plans/2026-07-23-low-priv-assumed-edges.md +1753 -0
  251. configmanbearpig-2.0.0/docs/superpowers/plans/2026-07-24-sccm-repo-cleanup.md +1047 -0
  252. configmanbearpig-2.0.0/docs/superpowers/plans/2026-07-29-multi-agent-concurrency.md +345 -0
  253. configmanbearpig-2.0.0/docs/superpowers/plans/2026-07-30-docs-update-readme-architecture.md +415 -0
  254. configmanbearpig-2.0.0/docs/superpowers/plans/2026-07-30-mssql-split-output.md +906 -0
  255. configmanbearpig-2.0.0/docs/superpowers/plans/2026-07-31-compare-and-privilege-gating.md +1729 -0
  256. configmanbearpig-2.0.0/docs/superpowers/specs/2026-05-26-ldap-management-points-raw-design.md +127 -0
  257. configmanbearpig-2.0.0/docs/superpowers/specs/2026-05-29-dns-resolver-flag-design.md +125 -0
  258. configmanbearpig-2.0.0/docs/superpowers/specs/2026-06-04-impacket-sspi-smb-sso-design.md +212 -0
  259. configmanbearpig-2.0.0/docs/superpowers/specs/2026-06-09-sccm-adminservice-collector-design.md +175 -0
  260. configmanbearpig-2.0.0/docs/superpowers/specs/2026-06-09-sccm-http-client-design.md +237 -0
  261. configmanbearpig-2.0.0/docs/superpowers/specs/2026-06-12-merge-privileged-collectors-design.md +186 -0
  262. configmanbearpig-2.0.0/docs/superpowers/specs/2026-06-15-smb-collector-design.md +207 -0
  263. configmanbearpig-2.0.0/docs/superpowers/specs/2026-06-16-sccm-preproc-convert-design.md +494 -0
  264. configmanbearpig-2.0.0/docs/superpowers/specs/2026-07-02-sccm-shared-lib-migration-design.md +263 -0
  265. configmanbearpig-2.0.0/docs/superpowers/specs/2026-07-15-edge-entity-panel-help-design.md +247 -0
  266. configmanbearpig-2.0.0/docs/superpowers/specs/2026-07-17-sccm-version-cve-fingerprint-design.md +187 -0
  267. configmanbearpig-2.0.0/docs/superpowers/specs/2026-07-22-sccm-integration-test-kit-design.md +143 -0
  268. configmanbearpig-2.0.0/docs/superpowers/specs/2026-07-23-cmbp-parity-node-edge-properties-design.md +143 -0
  269. configmanbearpig-2.0.0/docs/superpowers/specs/2026-07-23-low-priv-assumed-edges-design.md +411 -0
  270. configmanbearpig-2.0.0/docs/superpowers/specs/2026-07-27-publishing-and-repo-split-design.md +360 -0
  271. configmanbearpig-2.0.0/docs/superpowers/specs/2026-07-29-multi-agent-concurrency-design.md +415 -0
  272. configmanbearpig-2.0.0/docs/superpowers/specs/2026-07-31-compare-and-privilege-gating-design.md +259 -0
  273. configmanbearpig-2.0.0/powershell_deprecated/ConfigManBearPig.ps1 +10441 -0
  274. configmanbearpig-2.0.0/powershell_deprecated/Invoke-ConfigManBearPigUnitTests.ps1 +2019 -0
  275. configmanbearpig-2.0.0/powershell_deprecated/README.md +466 -0
  276. configmanbearpig-2.0.0/powershell_deprecated/RELEASE_NOTES.md +13 -0
  277. configmanbearpig-2.0.0/powershell_deprecated/bloodhound-sccm-20260801-133910.zip +0 -0
  278. configmanbearpig-2.0.0/powershell_deprecated/sample_data/upload_1_20260101144303_BloodHound_for_TAKEOVERs-3-and-8.zip +0 -0
  279. configmanbearpig-2.0.0/powershell_deprecated/sample_data/upload_1_bloodhound-sccm-noprivs-allpossibleedges-nobadopsec.zip +0 -0
  280. configmanbearpig-2.0.0/powershell_deprecated/sample_data/upload_2_bloodhound-sccm-noprivs-allpossibleedges-enablebadopsec.zip +0 -0
  281. configmanbearpig-2.0.0/powershell_deprecated/sample_data/upload_3_bloodhound-sccm-privileged.zip +0 -0
  282. configmanbearpig-2.0.0/powershell_deprecated/sample_data/upload_3_mssql-bloodhound-privileged.zip +0 -0
  283. configmanbearpig-2.0.0/powershell_deprecated/seed_data.json +50 -0
  284. configmanbearpig-2.0.0/pyproject.toml +224 -0
  285. configmanbearpig-2.0.0/sample_data/README.md +70 -0
  286. configmanbearpig-2.0.0/sample_data/configmanbearpig_collect_full_privileged_all-possible-edges_20260801_225955.log +3558 -0
  287. configmanbearpig-2.0.0/sample_data/configmanbearpig_collect_full_privileged_disable-possible-edges_20260801_230109.log +3560 -0
  288. configmanbearpig-2.0.0/sample_data/configmanbearpig_collect_full_unprivileged_all-possible-edges_20260801_230258.log +2222 -0
  289. configmanbearpig-2.0.0/sample_data/configmanbearpig_collect_full_unprivileged_disable-possible-edges_20260801_230714.log +2220 -0
  290. configmanbearpig-2.0.0/sample_data/configmanbearpig_collection_privileged_all-possible-edges_20260801_225955.zip +0 -0
  291. configmanbearpig-2.0.0/sample_data/configmanbearpig_collection_privileged_disable-possible-edges_20260801_230109.zip +0 -0
  292. configmanbearpig-2.0.0/sample_data/configmanbearpig_collection_unprivileged_all-possible-edges_20260801_230258.zip +0 -0
  293. configmanbearpig-2.0.0/sample_data/configmanbearpig_collection_unprivileged_disable-possible-edges_20260801_230714.zip +0 -0
  294. configmanbearpig-2.0.0/src/openhound_sccm/__init__.py +0 -0
  295. configmanbearpig-2.0.0/src/openhound_sccm/clients/__init__.py +0 -0
  296. configmanbearpig-2.0.0/src/openhound_sccm/clients/ad.py +296 -0
  297. configmanbearpig-2.0.0/src/openhound_sccm/clients/http.py +283 -0
  298. configmanbearpig-2.0.0/src/openhound_sccm/clients/http_auth.py +206 -0
  299. configmanbearpig-2.0.0/src/openhound_sccm/clients/mssql_epa.py +129 -0
  300. configmanbearpig-2.0.0/src/openhound_sccm/clients/smb.py +175 -0
  301. configmanbearpig-2.0.0/src/openhound_sccm/clients/smb_sso.py +289 -0
  302. configmanbearpig-2.0.0/src/openhound_sccm/clients/wmi.py +214 -0
  303. configmanbearpig-2.0.0/src/openhound_sccm/collectors/__init__.py +0 -0
  304. configmanbearpig-2.0.0/src/openhound_sccm/collectors/dns.py +278 -0
  305. configmanbearpig-2.0.0/src/openhound_sccm/collectors/http.py +559 -0
  306. configmanbearpig-2.0.0/src/openhound_sccm/collectors/ldap.py +879 -0
  307. configmanbearpig-2.0.0/src/openhound_sccm/collectors/local.py +349 -0
  308. configmanbearpig-2.0.0/src/openhound_sccm/collectors/mssql.py +179 -0
  309. configmanbearpig-2.0.0/src/openhound_sccm/collectors/privileged.py +423 -0
  310. configmanbearpig-2.0.0/src/openhound_sccm/collectors/registry.py +900 -0
  311. configmanbearpig-2.0.0/src/openhound_sccm/collectors/smb.py +295 -0
  312. configmanbearpig-2.0.0/src/openhound_sccm/collectors/sms_rows.py +102 -0
  313. configmanbearpig-2.0.0/src/openhound_sccm/collectors/stubs.py +43 -0
  314. configmanbearpig-2.0.0/src/openhound_sccm/context.py +467 -0
  315. configmanbearpig-2.0.0/src/openhound_sccm/convert_pipeline.py +180 -0
  316. configmanbearpig-2.0.0/src/openhound_sccm/cve_table.py +201 -0
  317. configmanbearpig-2.0.0/src/openhound_sccm/edge_help.py +1520 -0
  318. configmanbearpig-2.0.0/src/openhound_sccm/extension.yaml +71 -0
  319. configmanbearpig-2.0.0/src/openhound_sccm/graph.py +965 -0
  320. configmanbearpig-2.0.0/src/openhound_sccm/integration/__init__.py +86 -0
  321. configmanbearpig-2.0.0/src/openhound_sccm/integration/fixtures/__init__.py +36 -0
  322. configmanbearpig-2.0.0/src/openhound_sccm/integration/fixtures/edges.py +799 -0
  323. configmanbearpig-2.0.0/src/openhound_sccm/integration/fixtures/nodes.py +185 -0
  324. configmanbearpig-2.0.0/src/openhound_sccm/kinds/__init__.py +0 -0
  325. configmanbearpig-2.0.0/src/openhound_sccm/kinds/edges.py +88 -0
  326. configmanbearpig-2.0.0/src/openhound_sccm/kinds/nodes.py +35 -0
  327. configmanbearpig-2.0.0/src/openhound_sccm/log_context.py +110 -0
  328. configmanbearpig-2.0.0/src/openhound_sccm/lookup.py +42 -0
  329. configmanbearpig-2.0.0/src/openhound_sccm/main.py +2188 -0
  330. configmanbearpig-2.0.0/src/openhound_sccm/models/__init__.py +25 -0
  331. configmanbearpig-2.0.0/src/openhound_sccm/models/computer.py +123 -0
  332. configmanbearpig-2.0.0/src/openhound_sccm/models/container.py +73 -0
  333. configmanbearpig-2.0.0/src/openhound_sccm/models/graph_edge.py +126 -0
  334. configmanbearpig-2.0.0/src/openhound_sccm/models/group.py +116 -0
  335. configmanbearpig-2.0.0/src/openhound_sccm/models/mssql_database.py +50 -0
  336. configmanbearpig-2.0.0/src/openhound_sccm/models/mssql_database_role.py +50 -0
  337. configmanbearpig-2.0.0/src/openhound_sccm/models/mssql_database_user.py +53 -0
  338. configmanbearpig-2.0.0/src/openhound_sccm/models/mssql_login.py +50 -0
  339. configmanbearpig-2.0.0/src/openhound_sccm/models/mssql_server.py +71 -0
  340. configmanbearpig-2.0.0/src/openhound_sccm/models/mssql_server_role.py +48 -0
  341. configmanbearpig-2.0.0/src/openhound_sccm/models/raw_table.py +81 -0
  342. configmanbearpig-2.0.0/src/openhound_sccm/models/sccm_admin_user.py +99 -0
  343. configmanbearpig-2.0.0/src/openhound_sccm/models/sccm_client_device.py +156 -0
  344. configmanbearpig-2.0.0/src/openhound_sccm/models/sccm_collection.py +90 -0
  345. configmanbearpig-2.0.0/src/openhound_sccm/models/sccm_security_role.py +87 -0
  346. configmanbearpig-2.0.0/src/openhound_sccm/models/sccm_site.py +134 -0
  347. configmanbearpig-2.0.0/src/openhound_sccm/models/stub_node.py +60 -0
  348. configmanbearpig-2.0.0/src/openhound_sccm/models/target_entry.py +25 -0
  349. configmanbearpig-2.0.0/src/openhound_sccm/models/user.py +102 -0
  350. configmanbearpig-2.0.0/src/openhound_sccm/opengraph_untagged.py +57 -0
  351. configmanbearpig-2.0.0/src/openhound_sccm/per_host_phases.py +124 -0
  352. configmanbearpig-2.0.0/src/openhound_sccm/phased_pipeline/__init__.py +30 -0
  353. configmanbearpig-2.0.0/src/openhound_sccm/phased_pipeline/engine.py +136 -0
  354. configmanbearpig-2.0.0/src/openhound_sccm/phased_pipeline/streams.py +27 -0
  355. configmanbearpig-2.0.0/src/openhound_sccm/phased_pipeline/work_queue.py +84 -0
  356. configmanbearpig-2.0.0/src/openhound_sccm/schema_MSSQL.json +264 -0
  357. configmanbearpig-2.0.0/src/openhound_sccm/schema_SCCM.json +184 -0
  358. configmanbearpig-2.0.0/src/openhound_sccm/source.py +327 -0
  359. configmanbearpig-2.0.0/src/openhound_sccm/transforms.py +5963 -0
  360. configmanbearpig-2.0.0/tests/__init__.py +0 -0
  361. configmanbearpig-2.0.0/tests/ab_matrix_test.py +94 -0
  362. configmanbearpig-2.0.0/tests/ad_auth_warnings_test.py +135 -0
  363. configmanbearpig-2.0.0/tests/ad_node_props_emit_test.py +146 -0
  364. configmanbearpig-2.0.0/tests/ad_props_derive_test.py +123 -0
  365. configmanbearpig-2.0.0/tests/ad_pth_ptt_test.py +26 -0
  366. configmanbearpig-2.0.0/tests/ad_resolver_attrs_test.py +17 -0
  367. configmanbearpig-2.0.0/tests/ad_test.py +158 -0
  368. configmanbearpig-2.0.0/tests/allowed_targets_test.py +33 -0
  369. configmanbearpig-2.0.0/tests/assumed_site_db_test.py +320 -0
  370. configmanbearpig-2.0.0/tests/clean_output_test.py +116 -0
  371. configmanbearpig-2.0.0/tests/cli_argument_warnings_test.py +55 -0
  372. configmanbearpig-2.0.0/tests/cli_option_panels_test.py +209 -0
  373. configmanbearpig-2.0.0/tests/client_device_extras_test.py +175 -0
  374. configmanbearpig-2.0.0/tests/coerce_smb_traversable_test.py +59 -0
  375. configmanbearpig-2.0.0/tests/collect_exit_code_test.py +19 -0
  376. configmanbearpig-2.0.0/tests/collect_run_all_test.py +255 -0
  377. configmanbearpig-2.0.0/tests/collect_summary_test.py +198 -0
  378. configmanbearpig-2.0.0/tests/collection_settings_test.py +8 -0
  379. configmanbearpig-2.0.0/tests/computer_test.py +107 -0
  380. configmanbearpig-2.0.0/tests/conftest.py +8 -0
  381. configmanbearpig-2.0.0/tests/convert_integration_test.py +228 -0
  382. configmanbearpig-2.0.0/tests/convert_pipeline_test.py +179 -0
  383. configmanbearpig-2.0.0/tests/convert_split_output_test.py +97 -0
  384. configmanbearpig-2.0.0/tests/convert_untagged_emit_test.py +61 -0
  385. configmanbearpig-2.0.0/tests/cve_table_test.py +49 -0
  386. configmanbearpig-2.0.0/tests/dc_only_flag_test.py +44 -0
  387. configmanbearpig-2.0.0/tests/debug_exc_info_filter_test.py +319 -0
  388. configmanbearpig-2.0.0/tests/dedup_client_device_test.py +88 -0
  389. configmanbearpig-2.0.0/tests/disable_possible_env_override_test.py +53 -0
  390. configmanbearpig-2.0.0/tests/dns_resolver_flag_test.py +189 -0
  391. configmanbearpig-2.0.0/tests/edge_all_permissions_test.py +86 -0
  392. configmanbearpig-2.0.0/tests/edge_assign_all_permissions_test.py +133 -0
  393. configmanbearpig-2.0.0/tests/edge_coerce_relay_adminservice_gate_test.py +73 -0
  394. configmanbearpig-2.0.0/tests/edge_coerce_relay_adminservice_test.py +63 -0
  395. configmanbearpig-2.0.0/tests/edge_coerce_relay_mssql_test.py +212 -0
  396. configmanbearpig-2.0.0/tests/edge_coerce_relay_smb_test.py +63 -0
  397. configmanbearpig-2.0.0/tests/edge_contains_test.py +20 -0
  398. configmanbearpig-2.0.0/tests/edge_has_client_test.py +16 -0
  399. configmanbearpig-2.0.0/tests/edge_has_member_test.py +64 -0
  400. configmanbearpig-2.0.0/tests/edge_has_session_test.py +28 -0
  401. configmanbearpig-2.0.0/tests/edge_has_stored_account_test.py +14 -0
  402. configmanbearpig-2.0.0/tests/edge_has_user_test.py +27 -0
  403. configmanbearpig-2.0.0/tests/edge_help_assumed_test.py +108 -0
  404. configmanbearpig-2.0.0/tests/edge_help_emit_test.py +77 -0
  405. configmanbearpig-2.0.0/tests/edge_help_integration_test.py +133 -0
  406. configmanbearpig-2.0.0/tests/edge_help_test.py +62 -0
  407. configmanbearpig-2.0.0/tests/edge_is_assigned_test.py +29 -0
  408. configmanbearpig-2.0.0/tests/edge_is_mapped_to_sccminfra_test.py +119 -0
  409. configmanbearpig-2.0.0/tests/edge_is_mapped_to_test.py +25 -0
  410. configmanbearpig-2.0.0/tests/edge_local_admin_required_test.py +139 -0
  411. configmanbearpig-2.0.0/tests/edge_member_of_test.py +24 -0
  412. configmanbearpig-2.0.0/tests/edge_mssql_membership_test.py +43 -0
  413. configmanbearpig-2.0.0/tests/edge_mssql_service_account_test.py +50 -0
  414. configmanbearpig-2.0.0/tests/edge_mssql_structural_test.py +74 -0
  415. configmanbearpig-2.0.0/tests/edge_rbac_role_grants_test.py +73 -0
  416. configmanbearpig-2.0.0/tests/edge_same_host_test.py +62 -0
  417. configmanbearpig-2.0.0/tests/enrich_client_device_ad_domain_sid_test.py +110 -0
  418. configmanbearpig-2.0.0/tests/extension_metadata_test.py +34 -0
  419. configmanbearpig-2.0.0/tests/extension_methods_test.py +49 -0
  420. configmanbearpig-2.0.0/tests/graph_edge_relay_props_test.py +47 -0
  421. configmanbearpig-2.0.0/tests/graph_edge_test.py +29 -0
  422. configmanbearpig-2.0.0/tests/graph_edges_coercion_cols_test.py +74 -0
  423. configmanbearpig-2.0.0/tests/graph_edges_dedup_test.py +75 -0
  424. configmanbearpig-2.0.0/tests/graph_edges_split_test.py +71 -0
  425. configmanbearpig-2.0.0/tests/graph_edges_test.py +100 -0
  426. configmanbearpig-2.0.0/tests/graph_mssql_props_test.py +56 -0
  427. configmanbearpig-2.0.0/tests/graph_test.py +35 -0
  428. configmanbearpig-2.0.0/tests/group_test.py +113 -0
  429. configmanbearpig-2.0.0/tests/http_auth_test.py +115 -0
  430. configmanbearpig-2.0.0/tests/http_cli_flags_test.py +33 -0
  431. configmanbearpig-2.0.0/tests/http_client_test.py +257 -0
  432. configmanbearpig-2.0.0/tests/http_negotiate_integration_test.py +84 -0
  433. configmanbearpig-2.0.0/tests/http_test.py +524 -0
  434. configmanbearpig-2.0.0/tests/http_version_probe_test.py +69 -0
  435. configmanbearpig-2.0.0/tests/impacket_noise_filter_test.py +63 -0
  436. configmanbearpig-2.0.0/tests/integration_cli_flags_test.py +121 -0
  437. configmanbearpig-2.0.0/tests/integration_fixtures_test.py +88 -0
  438. configmanbearpig-2.0.0/tests/integration_lowpriv_fixtures_test.py +242 -0
  439. configmanbearpig-2.0.0/tests/integration_privilege_test.py +66 -0
  440. configmanbearpig-2.0.0/tests/integration_wiring_test.py +53 -0
  441. configmanbearpig-2.0.0/tests/kinds_edges_mssql_test.py +24 -0
  442. configmanbearpig-2.0.0/tests/kinds_edges_stage6_test.py +21 -0
  443. configmanbearpig-2.0.0/tests/kinds_edges_test.py +27 -0
  444. configmanbearpig-2.0.0/tests/ldap_cmrc_site_code_test.py +26 -0
  445. configmanbearpig-2.0.0/tests/ldap_management_points_raw_test.py +247 -0
  446. configmanbearpig-2.0.0/tests/ldap_resolved_principals_test.py +261 -0
  447. configmanbearpig-2.0.0/tests/ldap_smc_recursion_test.py +278 -0
  448. configmanbearpig-2.0.0/tests/local_log_scrape_regex_test.py +113 -0
  449. configmanbearpig-2.0.0/tests/local_resources_state_test.py +189 -0
  450. configmanbearpig-2.0.0/tests/local_wmi_ccm_test.py +139 -0
  451. configmanbearpig-2.0.0/tests/lookup_test.py +25 -0
  452. configmanbearpig-2.0.0/tests/lowpriv_end_to_end_test.py +356 -0
  453. configmanbearpig-2.0.0/tests/models_main_import_test.py +4 -0
  454. configmanbearpig-2.0.0/tests/mssql_epa_test.py +119 -0
  455. configmanbearpig-2.0.0/tests/mssql_kerberoast_spn_test.py +87 -0
  456. configmanbearpig-2.0.0/tests/mssql_models_test.py +74 -0
  457. configmanbearpig-2.0.0/tests/mssql_scaffold_possible_test.py +243 -0
  458. configmanbearpig-2.0.0/tests/mssql_service_account_spn_test.py +72 -0
  459. configmanbearpig-2.0.0/tests/mssql_spn_host_test.py +79 -0
  460. configmanbearpig-2.0.0/tests/mssql_spn_service_account_test.py +244 -0
  461. configmanbearpig-2.0.0/tests/node_admin_user_test.py +115 -0
  462. configmanbearpig-2.0.0/tests/node_authenticated_users_test.py +94 -0
  463. configmanbearpig-2.0.0/tests/node_backfill_test.py +24 -0
  464. configmanbearpig-2.0.0/tests/node_client_device_possible_test.py +53 -0
  465. configmanbearpig-2.0.0/tests/node_client_device_test.py +75 -0
  466. configmanbearpig-2.0.0/tests/node_collection_test.py +58 -0
  467. configmanbearpig-2.0.0/tests/node_computer_smb_signing_source_test.py +49 -0
  468. configmanbearpig-2.0.0/tests/node_computer_test.py +489 -0
  469. configmanbearpig-2.0.0/tests/node_group_test.py +231 -0
  470. configmanbearpig-2.0.0/tests/node_mssql_database_test.py +26 -0
  471. configmanbearpig-2.0.0/tests/node_mssql_login_dbuser_test.py +78 -0
  472. configmanbearpig-2.0.0/tests/node_mssql_roles_test.py +54 -0
  473. configmanbearpig-2.0.0/tests/node_mssql_server_test.py +104 -0
  474. configmanbearpig-2.0.0/tests/node_security_role_test.py +93 -0
  475. configmanbearpig-2.0.0/tests/node_site_cve_test.py +15 -0
  476. configmanbearpig-2.0.0/tests/node_site_http_version_test.py +60 -0
  477. configmanbearpig-2.0.0/tests/node_site_test.py +282 -0
  478. configmanbearpig-2.0.0/tests/node_user_test.py +243 -0
  479. configmanbearpig-2.0.0/tests/orphaned_role_sources_test.py +197 -0
  480. configmanbearpig-2.0.0/tests/per_host_integration_test.py +168 -0
  481. configmanbearpig-2.0.0/tests/per_host_log_blocks_test.py +124 -0
  482. configmanbearpig-2.0.0/tests/per_host_phases_streams_test.py +42 -0
  483. configmanbearpig-2.0.0/tests/per_host_phases_test.py +66 -0
  484. configmanbearpig-2.0.0/tests/per_host_wiring_test.py +90 -0
  485. configmanbearpig-2.0.0/tests/possible_client_provenance_test.py +79 -0
  486. configmanbearpig-2.0.0/tests/pp_engine_test.py +258 -0
  487. configmanbearpig-2.0.0/tests/pp_streams_test.py +52 -0
  488. configmanbearpig-2.0.0/tests/pp_work_queue_test.py +110 -0
  489. configmanbearpig-2.0.0/tests/preproc_map_test.py +128 -0
  490. configmanbearpig-2.0.0/tests/principal_resolution_referral_test.py +79 -0
  491. configmanbearpig-2.0.0/tests/privileged_test.py +320 -0
  492. configmanbearpig-2.0.0/tests/privileged_user_group_test.py +59 -0
  493. configmanbearpig-2.0.0/tests/progress_option_test.py +34 -0
  494. configmanbearpig-2.0.0/tests/provenance_test.py +26 -0
  495. configmanbearpig-2.0.0/tests/proxy_dns_test.py +55 -0
  496. configmanbearpig-2.0.0/tests/proxy_integration_test.py +112 -0
  497. configmanbearpig-2.0.0/tests/proxy_wiring_test.py +73 -0
  498. configmanbearpig-2.0.0/tests/regen_ticket_index_test.py +109 -0
  499. configmanbearpig-2.0.0/tests/registry_access_denied_test.py +132 -0
  500. configmanbearpig-2.0.0/tests/registry_collect_test.py +512 -0
  501. configmanbearpig-2.0.0/tests/registry_current_user_test.py +27 -0
  502. configmanbearpig-2.0.0/tests/registry_test.py +18 -0
  503. configmanbearpig-2.0.0/tests/sccm_admin_user_test.py +86 -0
  504. configmanbearpig-2.0.0/tests/sccm_client_device_test.py +83 -0
  505. configmanbearpig-2.0.0/tests/sccm_collection_test.py +51 -0
  506. configmanbearpig-2.0.0/tests/sccm_possible_edges_lowpriv_test.py +136 -0
  507. configmanbearpig-2.0.0/tests/sccm_security_role_test.py +55 -0
  508. configmanbearpig-2.0.0/tests/sccm_site_test.py +161 -0
  509. configmanbearpig-2.0.0/tests/secondary_site_db_test.py +132 -0
  510. configmanbearpig-2.0.0/tests/sharphound_naming_test.py +409 -0
  511. configmanbearpig-2.0.0/tests/site_hierarchy_lowpriv_test.py +339 -0
  512. configmanbearpig-2.0.0/tests/site_system_roles_test.py +96 -0
  513. configmanbearpig-2.0.0/tests/site_type_inference_test.py +106 -0
  514. configmanbearpig-2.0.0/tests/smb_sso_integration_test.py +36 -0
  515. configmanbearpig-2.0.0/tests/smb_sso_test.py +437 -0
  516. configmanbearpig-2.0.0/tests/smb_test.py +243 -0
  517. configmanbearpig-2.0.0/tests/smc_container_test.py +119 -0
  518. configmanbearpig-2.0.0/tests/smc_memberof_test.py +65 -0
  519. configmanbearpig-2.0.0/tests/sms_rows_test.py +41 -0
  520. configmanbearpig-2.0.0/tests/stub_node_test.py +19 -0
  521. configmanbearpig-2.0.0/tests/stub_per_host_phases.py +37 -0
  522. configmanbearpig-2.0.0/tests/transforms_dc_only_test.py +76 -0
  523. configmanbearpig-2.0.0/tests/transforms_hardening_test.py +161 -0
  524. configmanbearpig-2.0.0/tests/transforms_lookups_test.py +32 -0
  525. configmanbearpig-2.0.0/tests/transforms_principal_test.py +49 -0
  526. configmanbearpig-2.0.0/tests/transforms_safe_fallback_test.py +213 -0
  527. configmanbearpig-2.0.0/tests/transforms_settings_test.py +39 -0
  528. configmanbearpig-2.0.0/tests/transforms_test.py +41 -0
  529. configmanbearpig-2.0.0/tests/user_test.py +96 -0
  530. configmanbearpig-2.0.0/tests/verbose_silent_flags_test.py +173 -0
  531. configmanbearpig-2.0.0/tests/wmi_client_test.py +175 -0
  532. configmanbearpig-2.0.0/uv.lock +1901 -0
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: grill-me
3
+ description: Interview the user relentlessly about a plan or design until reaching shared understanding, resolving each branch of the decision tree. Use when the user wants to stress-test a plan, get grilled on their design, or mentions "grill me".
4
+ ---
5
+
6
+ Interview me relentlessly about every aspect of this plan until we reach a shared
7
+ understanding. Walk down each branch of the design tree, resolving dependencies between
8
+ decisions one-by-one. For each question, provide your recommended answer.
9
+
10
+ Ask the questions one at a time.
11
+
12
+ If a question can be answered by exploring the codebase, explore the codebase instead.
13
+
14
+ ## Why this file exists separately
15
+
16
+ This skill used to live as a second YAML frontmatter block inside
17
+ `.agents/skills/openhound/SKILL.md`. A skill loader reads the *first* frontmatter block in
18
+ a file and ignores the rest, so `grill-me` never resolved — and because a missing skill
19
+ degrades to "no instructions" rather than an error, every agent asked to use it silently
20
+ improvised instead. One skill per file.
@@ -0,0 +1,46 @@
1
+ ---
2
+ name: openhound
3
+ description: Use for all OpenHound collector work, including planning, graph schema, source collection, assets, lookup/preproc, registration, and validation.
4
+ ---
5
+
6
+ # OpenHound Development Skill
7
+
8
+ Use this skill for any OpenHound collector task.
9
+
10
+ ## Critical Rules (Always apply)
11
+
12
+ 1. Read `.agents/standards/openhound.md` before editing collector code. This includes important standards and best practices for OpenHound collector development that are not repeated in the reference docs.
13
+ 2. Based on the requested task, select the matching reference from the routing table. These contain specific rules and examples for different types of collector work.
14
+ 3. For broad collector work, or when creating a new collector, read `.agents/standards/workflow.md`.
15
+ 4. Important: Before finishing collector and graph behavior changes read `references/validate-extension.md`.
16
+
17
+ ### Route By Task
18
+
19
+ | Task | Reference |
20
+ |---|---|
21
+ | Plan a new collector from API docs, sample responses, or requirements | `references/plan-collector.md` |
22
+ | Define graph base classes, common properties, node IDs, or edge properties | `references/graph-schema.md` |
23
+ | Register `collect`, `preproc`, `convert`, metadata, or entry points | `references/register-extension.md` |
24
+ | Implement API clients, auth, DLT resources, transformers, or secrets | `references/source-collection.md` |
25
+ | Add or modify models, node assets, edge assets, kind constants, or exports | `references/add-asset.md` |
26
+ | Add DuckDB transforms, lookup methods, lookup registration, or `self._lookup` usage | `references/preproc-lookup.md` |
27
+ | Validate collector changes before finishing | `references/validate-extension.md` |
28
+
29
+ ### Routing Rules
30
+
31
+ - If the task touches multiple areas, read every matching reference.
32
+ - If adding or changing collector behavior, always read `references/validate-extension.md` before finishing.
33
+ - If the task involves a new collector or broad redesign, start with `references/plan-collector.md`.
34
+ - If models use `self._lookup`, also read `references/preproc-lookup.md` and `references/register-extension.md`.
35
+ - If adding a new collected resource, usually read `references/source-collection.md`, `references/add-asset.md`, and `references/validate-extension.md`.
36
+
37
+ ---
38
+ name: grill-me
39
+ description: Interview the user relentlessly about a plan or design until reaching shared understanding, resolving each branch of the decision tree. Use when user wants to stress-test a plan, get grilled on their design, or mentions "grill me".
40
+ ---
41
+
42
+ Interview me relentlessly about every aspect of this plan until we reach a shared understanding. Walk down each branch of the design tree, resolving dependencies between decisions one-by-one. For each question, provide your recommended answer.
43
+
44
+ Ask the questions one at a time.
45
+
46
+ If a question can be answered by exploring the codebase, explore the codebase instead.
@@ -0,0 +1,177 @@
1
+ # OpenHound Add Asset
2
+
3
+ Use this reference when adding a new resource model under `src/<pkg>/models/` or changing how a model emits nodes and edges.
4
+
5
+ ## Files Usually Touched
6
+
7
+ - `src/<pkg>/models/<name>.py`
8
+ - `src/<pkg>/models/__init__.py`
9
+ - `src/<pkg>/kinds/nodes.py`
10
+ - `src/<pkg>/kinds/edges.py`
11
+ - `src/<pkg>/source.py`
12
+ - `src/<pkg>/main.py` if lookup/preproc table registration is required
13
+ - `src/<pkg>/transforms.py` and `src/<pkg>/lookup.py` if cross-table lookup is required
14
+
15
+ ## Model Structure
16
+
17
+ Every collected asset should define two things:
18
+
19
+ 1. A dataclass named `<Name>Properties` extending the extension base `<PREFIX>NodeProperties`.
20
+ 2. A Pydantic `BaseAsset` subclass named `<Name>` decorated with `@app.asset(...)`.
21
+
22
+ The raw fields on the `BaseAsset` class should mirror the collected JSONL schema. The dataclass properties should describe the OpenGraph node properties emitted during conversion.
23
+
24
+ ## Property Dataclasses
25
+
26
+ Every OpenGraph property field must be documented in the class docstring's `Attributes` section:
27
+
28
+ ```python
29
+ from dataclasses import dataclass
30
+
31
+ from openhound_<pkg>.graph import EXNodeProperties
32
+
33
+
34
+ @dataclass
35
+ class AssetProperties(EXNodeProperties):
36
+ """Properties for the Asset node.
37
+
38
+ Attributes:
39
+ hostname: The asset hostname.
40
+ """
41
+ hostname: str
42
+ ```
43
+
44
+ Prefer nullable types over placeholder sentinels when data can be absent:
45
+
46
+ ```python
47
+ group_name: str | None = None
48
+ ```
49
+
50
+ Do not use empty strings to mean missing data unless the upstream API explicitly distinguishes empty string from null.
51
+
52
+ ## Asset Classes
53
+
54
+ Use `@app.asset(...)` with `NodeDef` for node-bearing assets and `EdgeDef` for relationships emitted by that same class.
55
+
56
+ ```python
57
+ from openhound.core.asset import BaseAsset, EdgeDef, NodeDef
58
+ from openhound.core.models.entries import Edge, EdgePath
59
+
60
+ from openhound_<pkg>.graph import EXNode
61
+ from openhound_<pkg>.kinds import edges as ek
62
+ from openhound_<pkg>.kinds import nodes as nk
63
+ from openhound_<pkg>.main import app
64
+
65
+
66
+ @app.asset(
67
+ node=NodeDef(kind=nk.ASSET, properties=AssetProperties, description="Example asset", icon="cog"),
68
+ edges=[
69
+ EdgeDef(
70
+ start=nk.ASSET,
71
+ end=nk.GROUP,
72
+ kind=ek.MEMBER_OF,
73
+ description="Asset belongs to group",
74
+ )
75
+ ],
76
+ )
77
+ class Asset(BaseAsset):
78
+ id: str
79
+ name: str
80
+ groups: list[str]
81
+
82
+ @property
83
+ def as_node(self) -> EXNode:
84
+ properties = AssetProperties(
85
+ node_id=self.id,
86
+ name=self.name,
87
+ displayname=self.name,
88
+ environmentid=self._extras["environmentid"],
89
+ )
90
+ return EXNode(properties=properties, kinds=[nk.ASSET])
91
+
92
+ @property
93
+ def edges(self):
94
+ for group_id in self.groups:
95
+ yield Edge(
96
+ kind=ek.MEMBER_OF,
97
+ start=EdgePath(value=self.as_node.id, match_by="id"),
98
+ end=EdgePath(value=group_id, match_by="id"),
99
+ )
100
+ ```
101
+
102
+ ## Edge Definition Alignment
103
+
104
+ Only declare `EdgeDef(...)` entries on the asset class that emits those edges from its `edges` property.
105
+
106
+ If a node-bearing asset creates only a node, use only `node=NodeDef(...)` and emit no edges. If relationships are represented by a separate edge-only asset, put the `EdgeDef(...)` declarations on that edge-only asset.
107
+
108
+ If a helper emits a shared edge, such as a root/environment containment edge, declare the matching `EdgeDef(...)` on every asset that yields it.
109
+
110
+ ## Edge Emission Style
111
+
112
+ Prefer generators:
113
+
114
+ ```python
115
+ @property
116
+ def _access_edges(self):
117
+ for target_id in self.target_ids:
118
+ yield Edge(...)
119
+
120
+ @property
121
+ def edges(self):
122
+ yield from self._access_edges
123
+ ```
124
+
125
+ Avoid building `edges = []`, appending items, and returning the list unless there is a specific reason.
126
+
127
+ ## Conditional Edge Paths
128
+
129
+ Prefer `ConditionalEdgePath` when creating an edge to an existing node that should be resolved by node properties instead of a known OpenGraph ID.
130
+
131
+ Use `PropertyMatch` entries for the stable property constraints needed to uniquely identify the target node. Avoid weak matchers, such as only `name`, unless the upstream domain guarantees uniqueness.
132
+
133
+ Use `EdgePath(value=..., match_by="id")` when the exact stable node ID is already known.
134
+
135
+ ```python
136
+ from openhound.core.models.entries import ConditionalEdgePath, Edge, EdgePath, PropertyMatch
137
+ from openhound.core.models.entries_dataclass import EdgeProperties
138
+
139
+
140
+ yield Edge(
141
+ kind=ek.MEMBERSHIP_SYNC,
142
+ start=ConditionalEdgePath(
143
+ kind=nk.GROUP,
144
+ property_matchers=[
145
+ PropertyMatch(key="tenant_domain", value=source_domain),
146
+ PropertyMatch(key="type", value="OKTA_GROUP"),
147
+ PropertyMatch(key="name", value=self.profile.name.upper()),
148
+ ],
149
+ ),
150
+ end=EdgePath(value=self.id, match_by="id"),
151
+ properties=EdgeProperties(traversable=True),
152
+ )
153
+ ```
154
+
155
+ ## Lookup Usage
156
+
157
+ Use `self._lookup` inside `as_node` or `edges` only when `preproc` creates and registers the required lookup data.
158
+
159
+ ```python
160
+ @property
161
+ def as_node(self) -> EXNode:
162
+ org_node_id = self._lookup.org_id_for(self.org_name)
163
+ properties = AssetProperties(node_id=self.id, org_id=org_node_id)
164
+ return EXNode(properties=properties, kinds=[nk.ASSET])
165
+ ```
166
+
167
+ ## Checklist
168
+
169
+ - Create or update `src/<pkg>/models/<name>.py`.
170
+ - Add node kind constants to `kinds/nodes.py` if the asset emits nodes.
171
+ - Add edge kind constants to `kinds/edges.py` if the asset emits edges.
172
+ - Assets returning a node must pass the emitted property dataclass into `NodeDef(properties=...)`.
173
+ - Export the model from `src/<pkg>/models/__init__.py`.
174
+ - Add or update a resource or transformer in `source.py`.
175
+ - Wire the resource or transformer into the source return tuple.
176
+ - If lookup data is needed, update `transforms.py`, `lookup.py`, and the `preproc` table map in `main.py`.
177
+ - Read `references/validate-extension.md` before finishing.
@@ -0,0 +1,114 @@
1
+ # OpenHound Graph Schema
2
+
3
+ Use this reference when editing `src/<pkg>/graph.py` or changing extension-wide OpenGraph node and edge property behavior.
4
+
5
+ ## Purpose
6
+
7
+ `graph.py` defines the OpenHound extension's base dataclass types for nodes, node properties, and edge properties. These types are imported by model files and lookup-related code.
8
+
9
+ ## Naming
10
+
11
+ Use the extension prefix consistently:
12
+
13
+ - `<PREFIX>NodeProperties`
14
+ - `<PREFIX>Node`
15
+ - `<PREFIX>EdgeProperties`
16
+
17
+ For example, GitHub might use `GHNodeProperties`, `GHNode`, and `GHEdgeProperties`.
18
+
19
+ ## Base Node Properties
20
+
21
+ The base properties class should extend `NodeProperties` from `openhound.core.models.entries_dataclass`.
22
+
23
+ Add only fields that every node in the extension should have.
24
+
25
+ ```python
26
+ from dataclasses import dataclass
27
+
28
+ from openhound.core.models.entries_dataclass import NodeProperties as BaseProperties
29
+
30
+
31
+ @dataclass
32
+ class EXNodeProperties(BaseProperties):
33
+ """Base properties for all nodes in the extension.
34
+
35
+ Attributes:
36
+ node_id: The platform native unique identifier.
37
+ """
38
+ node_id: str
39
+ ```
40
+
41
+ Every field must include docstrings specifying the attributes with a description because this is used for generated documentation.
42
+
43
+ Every collector should have one root/environment node. When a collector emits multiple resource nodes, include `environmentid` in the base node properties and set it to the OpenGraph ID of that root/environment node.
44
+
45
+ ## Node Class
46
+
47
+ The node class should extend `Node` from `openhound.core.models.entries_dataclass` and set `self.id` in `__post_init__`.
48
+
49
+ ```python
50
+ from dataclasses import dataclass, field
51
+
52
+ from openhound.core.models.entries_dataclass import Node as BaseNode
53
+
54
+
55
+ @dataclass
56
+ class EXNode(BaseNode):
57
+ properties: EXNodeProperties
58
+ kinds: list[str]
59
+ id: str = field(init=False)
60
+
61
+ def __post_init__(self):
62
+ self.id = self.properties.node_id
63
+ ```
64
+
65
+ ## Node ID Rules
66
+
67
+ Prefer the platform's native opaque/global node ID when available and only when the native ID is consistent and unique.
68
+
69
+ Do not use raw integer primary keys as OpenGraph node IDs. They are not stable enough across systems and can collide across extensions.
70
+
71
+ If the platform does not expose a suitable ID, derive one from stable properties with `BaseNode.guid(...)`:
72
+
73
+ ```python
74
+ def __post_init__(self):
75
+ self.id = self.guid(self.properties.tenant_id, self.properties.slug)
76
+ ```
77
+
78
+ Use reproducible values only. Do not include timestamps, random values, pagination offsets or mutable display names unless they are the best stable identifier the service provides.
79
+
80
+ ## Edge Properties
81
+
82
+ The extension edge property class should extend `EdgeProperties`.
83
+
84
+ ```python
85
+ from dataclasses import dataclass
86
+
87
+ from openhound.core.models.entries_dataclass import EdgeProperties
88
+
89
+
90
+ @dataclass
91
+ class EXEdgeProperties(EdgeProperties):
92
+ reason: str | None = None
93
+ ```
94
+
95
+ Add shared fields only when they apply broadly across extension edges. Entity-specific relationship fields can stay closer to the emitting model when appropriate.
96
+
97
+ ## Graph Schema Rules
98
+
99
+ - Keep `graph.py` generic to the extension, not specific to one entity.
100
+ - Avoid importing model classes into `graph.py`.
101
+ - Avoid importing `app` into `graph.py`.
102
+ - Do not define kind strings in `graph.py`; use `kinds/nodes.py` and `kinds/edges.py`.
103
+ - Do not add compatibility aliases unless there is persisted data, shipped behavior, external consumers, or an explicit requirement.
104
+
105
+ ## Checklist
106
+
107
+ - Prefix classes match the service prefix.
108
+ - Base node properties extend the OpenHound base properties class.
109
+ - Node class extends the OpenHound base node class.
110
+ - `id` is assigned in `__post_init__`.
111
+ - Node ID is stable and string-compatible.
112
+ - Base node properties include `environmentid` when the collector emits a root/environment node.
113
+ - Every graph property contains docstrings with an "Attributes" section describing each field.
114
+ - Read `references/validate-extension.md` before finishing.
@@ -0,0 +1,120 @@
1
+ # OpenHound Plan Collector
2
+
3
+ Use this reference before implementing a new collector or making broad collector changes. The output should be a concise design brief that maps the target service into OpenHound resources, graph nodes, edges, and follow-up implementation references.
4
+
5
+ Do not implement collection, models, lookup logic, or metadata from this reference. Use it to decide what should be built and in what order.
6
+
7
+ ## Inputs To Gather
8
+
9
+ - Target service name, slug, and intended short graph prefix.
10
+ - Authentication method, required credentials, and non-secret configuration values.
11
+ - API base URL, versioning model, pagination style, rate limits, and retry behavior.
12
+ - Primary resources to collect, such as users, groups, devices, roles, policies, repositories, or memberships.
13
+ - Sample API responses or schema references for each resource.
14
+ - Stable identifiers for each resource.
15
+ - Relationships between resources and whether they can be emitted directly or need lookup/preproc.
16
+ - Any sensitive fields that should not be collected or emitted.
17
+ - Expected commands or environments used to validate the collector.
18
+
19
+ If required information is missing, ask focused questions before designing implementation details.
20
+
21
+ ## Planning Checklist
22
+
23
+ ### 1. Service Identity
24
+
25
+ Define the collector identity:
26
+
27
+ - Source name and source_kind used by `OpenHound("<source>", source_kind=<kind>)`.
28
+ - Python package name, normally `openhound_<source>`.
29
+ - Short uppercase graph prefix, usually two to four characters.
30
+ - Extension metadata values for `extension.yaml`.
31
+
32
+ ### 2. Credentials And Configuration
33
+
34
+ List required secrets and parameters:
35
+
36
+ - DLT secret names expected under `[sources.source.<source>]`.
37
+ - Environment variable equivalents where useful.
38
+ - Non-secret parameters such as tenant, organization, region, or API host.
39
+ - Whether a dedicated `auth.py` module is likely needed.
40
+
41
+ ### 3. Resources To Collect
42
+
43
+ Create a resource inventory:
44
+
45
+ | Resource | API endpoint | DLT table | Model | Notes |
46
+ |---|---|---|---|---|
47
+ | users | `/users` | `users` | `User` | Example top-level resource. |
48
+
49
+ For each resource, decide whether it should be a top-level `@app.resource` or a nested `@app.transformer`.
50
+
51
+ ### 4. Graph Shape
52
+
53
+ Create a graph inventory:
54
+
55
+ | Node | Kind constant | Source resource | Stable ID | Notes |
56
+ |---|---|---|---|---|
57
+ | User | `USER` | `users` | Native user ID | Example node. |
58
+
59
+ Include one root/environment node for the collected environment. Other emitted nodes should set `environmentid` to that node's OpenGraph ID.
60
+
61
+ | Edge | Start | End | Source resource | Lookup needed |
62
+ |---|---|---|---|---|
63
+ | `MEMBER_OF` | User | Group | memberships | No |
64
+
65
+ Prefer native opaque/global IDs when available. Do not plan raw integer primary keys as OpenGraph node IDs unless they are converted into stable, collision-resistant IDs.
66
+
67
+ ### 5. Lookup And Preproc Needs
68
+
69
+ Identify where direct conversion is not enough:
70
+
71
+ - Relationships requiring joins across collected tables.
72
+ - Display or context fields that need enrichment from another table.
73
+ - Derived tables that should be created in `transforms.py`.
74
+ - Lookup methods that should be cached in `lookup.py`.
75
+
76
+ If no cross-table resolution is needed, explicitly say preproc/lookup is not required.
77
+
78
+ ### 6. Implementation Order
79
+
80
+ Map the plan to references:
81
+
82
+ 1. `references/graph-schema.md` for graph base types and ID strategy.
83
+ 2. `references/register-extension.md` for phase registration and metadata.
84
+ 3. `references/source-collection.md` for API resources and transformers.
85
+ 4. `references/add-asset.md` for each model, node, edge, and kind constant.
86
+ 5. `references/preproc-lookup.md` only when cross-table lookup is required.
87
+ 6. `references/validate-extension.md` before finishing.
88
+
89
+ ## Output Format
90
+
91
+ Produce a short collector design brief:
92
+
93
+ ```markdown
94
+ # Collector Plan: <Service>
95
+
96
+ ## Assumptions
97
+ - <assumption or question>
98
+
99
+ ## Credentials And Parameters
100
+ - <secret or parameter>
101
+
102
+ ## Resources
103
+ | Resource | API endpoint | DLT table | Model | Type |
104
+ |---|---|---|---|---|
105
+
106
+ ## Graph
107
+ | Node | Kind | Stable ID | Source |
108
+ |---|---|---|---|
109
+
110
+ | Edge | Start | End | Source | Lookup needed |
111
+ |---|---|---|---|---|
112
+
113
+ ## Preproc And Lookup
114
+ - <needed/not needed and why>
115
+
116
+ ## Implementation Sequence
117
+ 1. <reference and concrete target>
118
+ ```
119
+
120
+ Keep the brief practical. Avoid speculative resources, edges, or abstractions that are not supported by the target service requirements or API data.
@@ -0,0 +1,154 @@
1
+ # OpenHound Preproc And Lookup
2
+
3
+ Use this reference when relationships or node properties require data from multiple collected tables.
4
+
5
+ ## Purpose
6
+
7
+ `preproc` loads selected raw JSONL tables into DuckDB, runs optional SQL transforms and produces lookup data used during `convert` through `self._lookup`.
8
+
9
+ Use this path when a model needs to resolve information that is not present in its own raw row.
10
+
11
+ ## Files Usually Touched
12
+
13
+ - `src/<pkg>/transforms.py`
14
+ - `src/<pkg>/lookup.py`
15
+ - `src/<pkg>/main.py`
16
+ - `src/<pkg>/models/<name>.py`
17
+ - `src/<pkg>/source.py` if new raw tables must be collected
18
+
19
+ ## Transforms
20
+
21
+ `transforms.py` should contain plain DuckDB SQL functions. Keep each transform focused and call them from a top-level `transforms` function.
22
+
23
+ ```python
24
+ import duckdb
25
+
26
+
27
+ def create_joined_tables(con: duckdb.DuckDBPyConnection, schema: str = "myservice") -> None:
28
+ con.execute(
29
+ f"""
30
+ CREATE OR REPLACE TABLE {schema}.asset_groups AS
31
+ SELECT asset_id, group_id
32
+ FROM {schema}.asset_memberships
33
+ """
34
+ )
35
+
36
+
37
+ def transforms(con: duckdb.DuckDBPyConnection, schema: str = "myservice") -> None:
38
+ create_joined_tables(con, schema)
39
+ ```
40
+
41
+ Use parameter binding for values. Schema and table names are often interpolated because DuckDB does not bind identifiers; keep those values internal and trusted.
42
+
43
+ Use DuckDB JSON operators for JSON object fields loaded from raw resources:
44
+
45
+ ```sql
46
+ SELECT metadata->>'name' AS name
47
+ FROM myservice.assets
48
+ ```
49
+
50
+ ## Preproc Registration
51
+
52
+ The `preproc` function in `main.py` returns a mapping of DuckDB table name to JSONL table name. Only listed tables are loaded into the lookup DB.
53
+
54
+ ```python
55
+ @app.preproc(transformer=transforms)
56
+ def preproc(ctx: PreProcContext) -> dict[str, str]:
57
+ return {
58
+ "assets": "assets",
59
+ "asset_memberships": "asset_memberships",
60
+ }
61
+ ```
62
+
63
+ If no SQL transforms are needed, the transformer can be omitted. If lookup methods depend on transformed tables, ensure the transformer is registered.
64
+
65
+ If `lookup.py` reads a table created by `transforms.py`, use `@app.preproc(transformer=transforms)`.
66
+
67
+ ## Lookup Manager
68
+
69
+ `lookup.py` should define one extension lookup class extending `LookupManager`. Use `@lru_cache` for repeated lookups.
70
+
71
+ ```python
72
+ from functools import lru_cache
73
+
74
+ from openhound.core.lookup import LookupManager
75
+
76
+
77
+ class EXLookup(LookupManager):
78
+
79
+ def __init__(self, client: DuckDBPyConnection, schema: str = "myservice"):
80
+ super().__init__(client, schema)
81
+ self.schema = schema
82
+ self.client = client
83
+
84
+ @lru_cache
85
+ def group_id_for(self, name: str) -> str | None:
86
+ return self._find_single_object(
87
+ f"SELECT node_id FROM {self.schema}.groups WHERE name = ?",
88
+ [name],
89
+ )
90
+
91
+
92
+ @lru_cache
93
+ def all_assets_domain(self, domain: str) -> list:
94
+ return self._find_all_objects(
95
+ f"SELECT * FROM {self.schema}.assets WHERE domain = ?",
96
+ [domain],
97
+ )
98
+ ```
99
+
100
+ Prefer small lookup methods with clear names. The `_find_single_object` method will return `None` if no results are found.
101
+
102
+ ## Convert Registration
103
+
104
+ Register the lookup class on `@app.convert(...)`:
105
+
106
+ ```python
107
+ @app.convert(lookup=EXLookup)
108
+ def convert(ctx: ConvertContext) -> DltSource:
109
+ from .source import source as myservice_source
110
+
111
+ return myservice_source(), {}
112
+ ```
113
+
114
+ The lookup is injected into each `BaseAsset` as `self._lookup` during convert.
115
+
116
+ ## Model Usage
117
+
118
+ Use lookup methods from `as_node` or `edges` when needed:
119
+
120
+ ```python
121
+ @property
122
+ def edges(self):
123
+ group_id = self._lookup.group_id_for(self.group_name)
124
+ if group_id is None:
125
+ return
126
+
127
+ yield Edge(
128
+ kind=ek.MEMBER_OF,
129
+ start=EdgePath(value=self.as_node.id, match_by="id"),
130
+ end=EdgePath(value=group_id, match_by="id"),
131
+ )
132
+ ```
133
+
134
+ Document in the collector README when users must run `preproc` before `convert`.
135
+
136
+ ## Rules
137
+
138
+ - Do not call `self._lookup` unless `convert` is registered with the lookup class.
139
+ - Do not assume raw tables are available in DuckDB unless they are returned by `preproc`.
140
+ - Keep transform output table names stable; lookup methods may depend on them.
141
+ - Avoid loading unnecessary raw tables into preproc.
142
+ - Cache deterministic lookup methods with `@lru_cache` or `@cache`.
143
+
144
+ ## Checklist
145
+
146
+ - Required raw tables are collected by `source.py` and match with the defined resource/transformer name.
147
+ - Required raw tables are included in `main.py`'s `preproc` mapping.
148
+ - SQL transforms create any derived tables used by lookup methods.
149
+ - `@app.preproc(transformer=transforms)` is used when transforms are required.
150
+ - `@app.preproc(transformer=transforms)` is used when lookup reads transformed tables.
151
+ - `lookup.py` contains cached lookup methods.
152
+ - `@app.convert(lookup=<PREFIX>Lookup)` is registered.
153
+ - Models handle missing lookup results.
154
+ - Read `references/validate-extension.md` before finishing.