temper-rb 0.5.1

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 (384) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +291 -0
  4. data/lib/temper/act.rb +47 -0
  5. data/lib/temper/client.rb +96 -0
  6. data/lib/temper/cognitive_maps.rb +75 -0
  7. data/lib/temper/connection.rb +113 -0
  8. data/lib/temper/contexts.rb +54 -0
  9. data/lib/temper/credentials.rb +138 -0
  10. data/lib/temper/errors.rb +154 -0
  11. data/lib/temper/generated/api/access_api.rb +356 -0
  12. data/lib/temper/generated/api/auditor_api.rb +228 -0
  13. data/lib/temper/generated/api/blobs_api.rb +785 -0
  14. data/lib/temper/generated/api/cognitive_maps_api.rb +996 -0
  15. data/lib/temper/generated/api/contexts_api.rb +1039 -0
  16. data/lib/temper/generated/api/data_artifact_shapes_api.rb +243 -0
  17. data/lib/temper/generated/api/data_artifacts_api.rb +261 -0
  18. data/lib/temper/generated/api/events_api.rb +164 -0
  19. data/lib/temper/generated/api/facets_api.rb +406 -0
  20. data/lib/temper/generated/api/graph_api.rb +612 -0
  21. data/lib/temper/generated/api/health_api.rb +84 -0
  22. data/lib/temper/generated/api/ingest_api.rb +398 -0
  23. data/lib/temper/generated/api/invitations_api.rb +514 -0
  24. data/lib/temper/generated/api/invocations_api.rb +308 -0
  25. data/lib/temper/generated/api/meta_api.rb +169 -0
  26. data/lib/temper/generated/api/profile_api.rb +219 -0
  27. data/lib/temper/generated/api/query_api.rb +97 -0
  28. data/lib/temper/generated/api/reblocking_api.rb +95 -0
  29. data/lib/temper/generated/api/relationships_api.rb +332 -0
  30. data/lib/temper/generated/api/resources_api.rb +1329 -0
  31. data/lib/temper/generated/api/schema_api.rb +218 -0
  32. data/lib/temper/generated/api/search_api.rb +97 -0
  33. data/lib/temper/generated/api/slack_link_api.rb +159 -0
  34. data/lib/temper/generated/api/steward_api.rb +372 -0
  35. data/lib/temper/generated/api/teams_api.rb +687 -0
  36. data/lib/temper/generated/api_client.rb +441 -0
  37. data/lib/temper/generated/api_error.rb +58 -0
  38. data/lib/temper/generated/api_model_base.rb +88 -0
  39. data/lib/temper/generated/configuration.rb +393 -0
  40. data/lib/temper/generated/models/accept_invitation_response.rb +239 -0
  41. data/lib/temper/generated/models/act_input.rb +238 -0
  42. data/lib/temper/generated/models/act_invocation.rb +271 -0
  43. data/lib/temper/generated/models/act_name.rb +104 -0
  44. data/lib/temper/generated/models/act_quantity.rb +219 -0
  45. data/lib/temper/generated/models/act_refusal.rb +192 -0
  46. data/lib/temper/generated/models/actor_authority.rb +41 -0
  47. data/lib/temper/generated/models/add_member_request.rb +213 -0
  48. data/lib/temper/generated/models/advance_watermark_ack.rb +188 -0
  49. data/lib/temper/generated/models/advance_watermark_request.rb +161 -0
  50. data/lib/temper/generated/models/agent_authorship.rb +227 -0
  51. data/lib/temper/generated/models/anchor_address_resolution.rb +106 -0
  52. data/lib/temper/generated/models/anchor_address_resolution_one_of.rb +189 -0
  53. data/lib/temper/generated/models/anchor_address_resolution_one_of1.rb +242 -0
  54. data/lib/temper/generated/models/anchor_address_resolution_one_of2.rb +189 -0
  55. data/lib/temper/generated/models/anchor_shape.rb +239 -0
  56. data/lib/temper/generated/models/anchor_verdict.rb +41 -0
  57. data/lib/temper/generated/models/append_block_payload.rb +250 -0
  58. data/lib/temper/generated/models/artifact_commit_request.rb +337 -0
  59. data/lib/temper/generated/models/artifact_commit_response.rb +192 -0
  60. data/lib/temper/generated/models/artifact_view.rb +466 -0
  61. data/lib/temper/generated/models/assert_relationship_request.rb +406 -0
  62. data/lib/temper/generated/models/atlas_edge.rb +327 -0
  63. data/lib/temper/generated/models/atlas_entry.rb +221 -0
  64. data/lib/temper/generated/models/atlas_home.rb +195 -0
  65. data/lib/temper/generated/models/atlas_node.rb +329 -0
  66. data/lib/temper/generated/models/atlas_subgraph.rb +195 -0
  67. data/lib/temper/generated/models/audit_citation.rb +220 -0
  68. data/lib/temper/generated/models/audit_sweep_row.rb +220 -0
  69. data/lib/temper/generated/models/auditor_dispatch_tick_request.rb +150 -0
  70. data/lib/temper/generated/models/auditor_dispatch_tick_response.rb +178 -0
  71. data/lib/temper/generated/models/auditor_job_complete_ack.rb +175 -0
  72. data/lib/temper/generated/models/bind_team_outcome.rb +218 -0
  73. data/lib/temper/generated/models/bind_team_request.rb +166 -0
  74. data/lib/temper/generated/models/blob_commit_response.rb +283 -0
  75. data/lib/temper/generated/models/blob_delete_ack.rb +191 -0
  76. data/lib/temper/generated/models/blob_relation_ack.rb +165 -0
  77. data/lib/temper/generated/models/blob_relation_assert_request.rb +404 -0
  78. data/lib/temper/generated/models/blob_relation_direction.rb +40 -0
  79. data/lib/temper/generated/models/blob_relation_edge_direction.rb +40 -0
  80. data/lib/temper/generated/models/blob_relation_row.rb +390 -0
  81. data/lib/temper/generated/models/blob_summary.rb +256 -0
  82. data/lib/temper/generated/models/blob_upload_begin_request.rb +219 -0
  83. data/lib/temper/generated/models/blob_upload_begin_response.rb +165 -0
  84. data/lib/temper/generated/models/blob_upload_finalize_request.rb +211 -0
  85. data/lib/temper/generated/models/blob_upload_progress.rb +220 -0
  86. data/lib/temper/generated/models/blob_upload_segment_info.rb +227 -0
  87. data/lib/temper/generated/models/block_chunk_ref.rb +217 -0
  88. data/lib/temper/generated/models/block_fold_disposition.rb +106 -0
  89. data/lib/temper/generated/models/block_fold_disposition_one_of.rb +245 -0
  90. data/lib/temper/generated/models/block_fold_disposition_one_of1.rb +189 -0
  91. data/lib/temper/generated/models/block_fold_disposition_one_of2.rb +189 -0
  92. data/lib/temper/generated/models/block_provenance_row.rb +348 -0
  93. data/lib/temper/generated/models/block_read.rb +106 -0
  94. data/lib/temper/generated/models/block_read_one_of.rb +311 -0
  95. data/lib/temper/generated/models/block_read_one_of1.rb +297 -0
  96. data/lib/temper/generated/models/block_read_one_of2.rb +215 -0
  97. data/lib/temper/generated/models/block_successor.rb +177 -0
  98. data/lib/temper/generated/models/blocks_response.rb +194 -0
  99. data/lib/temper/generated/models/body_storage.rb +40 -0
  100. data/lib/temper/generated/models/bridge.rb +217 -0
  101. data/lib/temper/generated/models/bulk_reassign_ack.rb +167 -0
  102. data/lib/temper/generated/models/bulk_reassign_request.rb +191 -0
  103. data/lib/temper/generated/models/change_role_request.rb +187 -0
  104. data/lib/temper/generated/models/charter_block.rb +220 -0
  105. data/lib/temper/generated/models/charter_disposition.rb +42 -0
  106. data/lib/temper/generated/models/citation_audit_request.rb +231 -0
  107. data/lib/temper/generated/models/citation_audit_row.rb +366 -0
  108. data/lib/temper/generated/models/claimed_audit_job.rb +249 -0
  109. data/lib/temper/generated/models/claimed_job.rb +220 -0
  110. data/lib/temper/generated/models/close_invocation_request.rb +197 -0
  111. data/lib/temper/generated/models/cogmap_analytics_row.rb +220 -0
  112. data/lib/temper/generated/models/cogmap_detail.rb +224 -0
  113. data/lib/temper/generated/models/cogmap_foundation_row.rb +247 -0
  114. data/lib/temper/generated/models/cogmap_grant_body.rb +295 -0
  115. data/lib/temper/generated/models/cogmap_region_metrics_row.rb +248 -0
  116. data/lib/temper/generated/models/cogmap_region_row.rb +269 -0
  117. data/lib/temper/generated/models/cogmap_regulation_row.rb +228 -0
  118. data/lib/temper/generated/models/cogmap_revoke_body.rb +191 -0
  119. data/lib/temper/generated/models/cogmap_row.rb +341 -0
  120. data/lib/temper/generated/models/cogmap_staleness.rb +185 -0
  121. data/lib/temper/generated/models/combine_node.rb +263 -0
  122. data/lib/temper/generated/models/combine_op.rb +41 -0
  123. data/lib/temper/generated/models/composition.rb +203 -0
  124. data/lib/temper/generated/models/composition_trace.rb +167 -0
  125. data/lib/temper/generated/models/confidence_band.rb +41 -0
  126. data/lib/temper/generated/models/content_response.rb +213 -0
  127. data/lib/temper/generated/models/context_create_request.rb +176 -0
  128. data/lib/temper/generated/models/context_owner_ref.rb +106 -0
  129. data/lib/temper/generated/models/context_owner_ref_one_of.rb +166 -0
  130. data/lib/temper/generated/models/context_owner_ref_one_of1.rb +166 -0
  131. data/lib/temper/generated/models/context_panorama.rb +221 -0
  132. data/lib/temper/generated/models/context_row.rb +404 -0
  133. data/lib/temper/generated/models/context_row_with_counts.rb +430 -0
  134. data/lib/temper/generated/models/create_cogmap_outcome.rb +217 -0
  135. data/lib/temper/generated/models/create_cogmap_request.rb +221 -0
  136. data/lib/temper/generated/models/create_invitation_request.rb +213 -0
  137. data/lib/temper/generated/models/create_request_body.rb +184 -0
  138. data/lib/temper/generated/models/create_review_body.rb +148 -0
  139. data/lib/temper/generated/models/deactivated.rb +189 -0
  140. data/lib/temper/generated/models/delete_response.rb +165 -0
  141. data/lib/temper/generated/models/denied.rb +189 -0
  142. data/lib/temper/generated/models/device_overrides.rb +162 -0
  143. data/lib/temper/generated/models/discouraged_open_meta_key.rb +191 -0
  144. data/lib/temper/generated/models/dispatch_tick_request.rb +161 -0
  145. data/lib/temper/generated/models/dispatch_tick_response.rb +178 -0
  146. data/lib/temper/generated/models/disposition.rb +41 -0
  147. data/lib/temper/generated/models/doc_type_description.rb +247 -0
  148. data/lib/temper/generated/models/doc_type_summary.rb +219 -0
  149. data/lib/temper/generated/models/drift_sweep_row.rb +258 -0
  150. data/lib/temper/generated/models/edge_facet_row.rb +332 -0
  151. data/lib/temper/generated/models/edge_facet_set_request.rb +288 -0
  152. data/lib/temper/generated/models/edge_facets_response.rb +193 -0
  153. data/lib/temper/generated/models/edge_filter.rb +192 -0
  154. data/lib/temper/generated/models/edge_kind.rb +42 -0
  155. data/lib/temper/generated/models/element_event.rb +307 -0
  156. data/lib/temper/generated/models/element_kind.rb +40 -0
  157. data/lib/temper/generated/models/embed_dispatch_summary.rb +355 -0
  158. data/lib/temper/generated/models/enforcement_mode.rb +40 -0
  159. data/lib/temper/generated/models/entitlements.rb +234 -0
  160. data/lib/temper/generated/models/entry_bounds.rb +247 -0
  161. data/lib/temper/generated/models/error_body.rb +164 -0
  162. data/lib/temper/generated/models/error_detail.rb +201 -0
  163. data/lib/temper/generated/models/error_details.rb +105 -0
  164. data/lib/temper/generated/models/event_cursor_response.rb +150 -0
  165. data/lib/temper/generated/models/event_trail.rb +241 -0
  166. data/lib/temper/generated/models/exact_arm.rb +226 -0
  167. data/lib/temper/generated/models/exact_hit.rb +193 -0
  168. data/lib/temper/generated/models/extent.rb +106 -0
  169. data/lib/temper/generated/models/extent_one_of.rb +189 -0
  170. data/lib/temper/generated/models/extent_one_of1.rb +189 -0
  171. data/lib/temper/generated/models/extent_one_of2.rb +215 -0
  172. data/lib/temper/generated/models/facet_ack.rb +168 -0
  173. data/lib/temper/generated/models/facet_predicate.rb +191 -0
  174. data/lib/temper/generated/models/facet_retract_ack.rb +165 -0
  175. data/lib/temper/generated/models/facet_set_request.rb +304 -0
  176. data/lib/temper/generated/models/finalize_payload.rb +212 -0
  177. data/lib/temper/generated/models/fold_relationship_request.rb +248 -0
  178. data/lib/temper/generated/models/grant_outcome.rb +166 -0
  179. data/lib/temper/generated/models/graph_edge_row.rb +421 -0
  180. data/lib/temper/generated/models/group_key_meta.rb +217 -0
  181. data/lib/temper/generated/models/health_response.rb +202 -0
  182. data/lib/temper/generated/models/home_cogmap.rb +297 -0
  183. data/lib/temper/generated/models/home_context.rb +281 -0
  184. data/lib/temper/generated/models/id_kind.rb +104 -0
  185. data/lib/temper/generated/models/id_provenance.rb +105 -0
  186. data/lib/temper/generated/models/id_provenance_one_of.rb +215 -0
  187. data/lib/temper/generated/models/id_provenance_one_of1.rb +215 -0
  188. data/lib/temper/generated/models/id_set.rb +214 -0
  189. data/lib/temper/generated/models/idp_revocation.rb +41 -0
  190. data/lib/temper/generated/models/illegal_transition.rb +225 -0
  191. data/lib/temper/generated/models/ingest_create_response.rb +105 -0
  192. data/lib/temper/generated/models/ingest_delta.rb +334 -0
  193. data/lib/temper/generated/models/ingest_payload.rb +478 -0
  194. data/lib/temper/generated/models/ingest_state.rb +40 -0
  195. data/lib/temper/generated/models/inherited_read_grant.rb +219 -0
  196. data/lib/temper/generated/models/inherited_share.rb +192 -0
  197. data/lib/temper/generated/models/input_source.rb +106 -0
  198. data/lib/temper/generated/models/input_source_one_of.rb +227 -0
  199. data/lib/temper/generated/models/input_source_one_of1.rb +189 -0
  200. data/lib/temper/generated/models/input_source_one_of2.rb +189 -0
  201. data/lib/temper/generated/models/insufficient_authority.rb +241 -0
  202. data/lib/temper/generated/models/intention.rb +212 -0
  203. data/lib/temper/generated/models/invitation_status.rb +42 -0
  204. data/lib/temper/generated/models/invitation_token_request.rb +165 -0
  205. data/lib/temper/generated/models/invitee_invitation.rb +447 -0
  206. data/lib/temper/generated/models/invocation_ack.rb +191 -0
  207. data/lib/temper/generated/models/invocation_act_row.rb +269 -0
  208. data/lib/temper/generated/models/invocation_close_ack.rb +213 -0
  209. data/lib/temper/generated/models/invocation_summary.rb +296 -0
  210. data/lib/temper/generated/models/invocation_view.rb +433 -0
  211. data/lib/temper/generated/models/join_request.rb +403 -0
  212. data/lib/temper/generated/models/join_request_status.rb +42 -0
  213. data/lib/temper/generated/models/kind_owner_input.rb +105 -0
  214. data/lib/temper/generated/models/kind_owner_input_one_of.rb +164 -0
  215. data/lib/temper/generated/models/kind_owner_input_one_of1.rb +164 -0
  216. data/lib/temper/generated/models/lineage_node.rb +326 -0
  217. data/lib/temper/generated/models/managed_meta.rb +249 -0
  218. data/lib/temper/generated/models/match_location.rb +188 -0
  219. data/lib/temper/generated/models/materialize_ack.rb +307 -0
  220. data/lib/temper/generated/models/materialize_delta.rb +296 -0
  221. data/lib/temper/generated/models/materialize_request.rb +150 -0
  222. data/lib/temper/generated/models/merge_policy.rb +40 -0
  223. data/lib/temper/generated/models/meta_update_payload.rb +358 -0
  224. data/lib/temper/generated/models/narrowed_by.rb +210 -0
  225. data/lib/temper/generated/models/no_prior_standing.rb +189 -0
  226. data/lib/temper/generated/models/no_standing.rb +189 -0
  227. data/lib/temper/generated/models/node_home.rb +40 -0
  228. data/lib/temper/generated/models/open_invocation_request.rb +204 -0
  229. data/lib/temper/generated/models/open_meta_convention.rb +180 -0
  230. data/lib/temper/generated/models/ord_op.rb +42 -0
  231. data/lib/temper/generated/models/orphan_node.rb +264 -0
  232. data/lib/temper/generated/models/outcome_declaration.rb +177 -0
  233. data/lib/temper/generated/models/pending_invitation_counts.rb +177 -0
  234. data/lib/temper/generated/models/plan_refusal.rb +220 -0
  235. data/lib/temper/generated/models/plan_refusal_details.rb +167 -0
  236. data/lib/temper/generated/models/polarity.rb +40 -0
  237. data/lib/temper/generated/models/profile.rb +313 -0
  238. data/lib/temper/generated/models/profile_auth_link.rb +332 -0
  239. data/lib/temper/generated/models/profile_update_request.rb +169 -0
  240. data/lib/temper/generated/models/profile_with_entitlements.rb +344 -0
  241. data/lib/temper/generated/models/property_op.rb +106 -0
  242. data/lib/temper/generated/models/property_op_one_of.rb +189 -0
  243. data/lib/temper/generated/models/property_op_one_of1.rb +217 -0
  244. data/lib/temper/generated/models/property_op_one_of2.rb +227 -0
  245. data/lib/temper/generated/models/property_predicate.rb +191 -0
  246. data/lib/temper/generated/models/provenance_source.rb +106 -0
  247. data/lib/temper/generated/models/provenance_source_one_of.rb +214 -0
  248. data/lib/temper/generated/models/provenance_source_one_of1.rb +214 -0
  249. data/lib/temper/generated/models/provenance_source_one_of2.rb +216 -0
  250. data/lib/temper/generated/models/public_system_settings.rb +169 -0
  251. data/lib/temper/generated/models/quantity_scale.rb +106 -0
  252. data/lib/temper/generated/models/quantity_scale_one_of.rb +189 -0
  253. data/lib/temper/generated/models/quantity_scale_one_of1.rb +215 -0
  254. data/lib/temper/generated/models/quantity_scale_one_of2.rb +189 -0
  255. data/lib/temper/generated/models/query_response.rb +195 -0
  256. data/lib/temper/generated/models/reassign_ack.rb +191 -0
  257. data/lib/temper/generated/models/reassign_context_outcome.rb +243 -0
  258. data/lib/temper/generated/models/reassign_context_request.rb +166 -0
  259. data/lib/temper/generated/models/reassign_resource_request.rb +165 -0
  260. data/lib/temper/generated/models/reblock_candidate.rb +192 -0
  261. data/lib/temper/generated/models/reblock_outcome.rb +109 -0
  262. data/lib/temper/generated/models/reblock_outcome_one_of.rb +165 -0
  263. data/lib/temper/generated/models/reblock_outcome_one_of1.rb +165 -0
  264. data/lib/temper/generated/models/reblock_outcome_one_of1_in_progress.rb +166 -0
  265. data/lib/temper/generated/models/reblock_outcome_one_of2.rb +165 -0
  266. data/lib/temper/generated/models/reblock_outcome_one_of3.rb +165 -0
  267. data/lib/temper/generated/models/reblock_outcome_one_of4.rb +165 -0
  268. data/lib/temper/generated/models/reblock_outcome_one_of4_error.rb +165 -0
  269. data/lib/temper/generated/models/reblock_outcome_one_of_reblocked.rb +165 -0
  270. data/lib/temper/generated/models/reblock_receipt.rb +259 -0
  271. data/lib/temper/generated/models/reblock_request.rb +215 -0
  272. data/lib/temper/generated/models/reblock_scope.rb +106 -0
  273. data/lib/temper/generated/models/reblock_scope_one_of.rb +166 -0
  274. data/lib/temper/generated/models/reblock_scope_one_of1.rb +166 -0
  275. data/lib/temper/generated/models/reblock_summary.rb +350 -0
  276. data/lib/temper/generated/models/reconcile_cogmap_request.rb +199 -0
  277. data/lib/temper/generated/models/reconcile_edge.rb +253 -0
  278. data/lib/temper/generated/models/reconcile_edge_tombstone.rb +217 -0
  279. data/lib/temper/generated/models/reconcile_entry.rb +318 -0
  280. data/lib/temper/generated/models/reconcile_outcome.rb +327 -0
  281. data/lib/temper/generated/models/reconcile_telos.rb +167 -0
  282. data/lib/temper/generated/models/reconcile_telos_block.rb +191 -0
  283. data/lib/temper/generated/models/reconcile_tombstone.rb +165 -0
  284. data/lib/temper/generated/models/refusal.rb +112 -0
  285. data/lib/temper/generated/models/refusal_reason.rb +104 -0
  286. data/lib/temper/generated/models/region_disclosure.rb +193 -0
  287. data/lib/temper/generated/models/region_hit.rb +192 -0
  288. data/lib/temper/generated/models/relationship_ack.rb +165 -0
  289. data/lib/temper/generated/models/relationship_target.rb +40 -0
  290. data/lib/temper/generated/models/remove_member_outcome.rb +165 -0
  291. data/lib/temper/generated/models/rename_context_outcome.rb +300 -0
  292. data/lib/temper/generated/models/rename_context_request.rb +166 -0
  293. data/lib/temper/generated/models/requested.rb +189 -0
  294. data/lib/temper/generated/models/residual_bucket.rb +191 -0
  295. data/lib/temper/generated/models/residual_context.rb +201 -0
  296. data/lib/temper/generated/models/residual_groups.rb +193 -0
  297. data/lib/temper/generated/models/residual_owned_reach.rb +202 -0
  298. data/lib/temper/generated/models/resource_annotate_request.rb +261 -0
  299. data/lib/temper/generated/models/resource_create_request.rb +355 -0
  300. data/lib/temper/generated/models/resource_facet_row.rb +317 -0
  301. data/lib/temper/generated/models/resource_facets.rb +226 -0
  302. data/lib/temper/generated/models/resource_facets_response.rb +193 -0
  303. data/lib/temper/generated/models/resource_filter.rb +265 -0
  304. data/lib/temper/generated/models/resource_grant_body.rb +295 -0
  305. data/lib/temper/generated/models/resource_hit.rb +216 -0
  306. data/lib/temper/generated/models/resource_lineage.rb +224 -0
  307. data/lib/temper/generated/models/resource_list_response.rb +313 -0
  308. data/lib/temper/generated/models/resource_revoke_body.rb +191 -0
  309. data/lib/temper/generated/models/resource_section.rb +41 -0
  310. data/lib/temper/generated/models/resource_sort_field.rb +45 -0
  311. data/lib/temper/generated/models/resource_update_request.rb +379 -0
  312. data/lib/temper/generated/models/resource_view.rb +592 -0
  313. data/lib/temper/generated/models/restore_context_outcome.rb +274 -0
  314. data/lib/temper/generated/models/retire_context_outcome.rb +247 -0
  315. data/lib/temper/generated/models/return_spec.rb +189 -0
  316. data/lib/temper/generated/models/retype_relationship_request.rb +290 -0
  317. data/lib/temper/generated/models/revoke_outcome.rb +165 -0
  318. data/lib/temper/generated/models/revoked.rb +189 -0
  319. data/lib/temper/generated/models/reweight_relationship_request.rb +264 -0
  320. data/lib/temper/generated/models/score_kind.rb +104 -0
  321. data/lib/temper/generated/models/scoring.rb +192 -0
  322. data/lib/temper/generated/models/search_params.rb +254 -0
  323. data/lib/temper/generated/models/search_reason.rb +41 -0
  324. data/lib/temper/generated/models/search_response.rb +217 -0
  325. data/lib/temper/generated/models/search_result_row.rb +343 -0
  326. data/lib/temper/generated/models/search_scope.rb +41 -0
  327. data/lib/temper/generated/models/search_scope_info.rb +199 -0
  328. data/lib/temper/generated/models/segment_info.rb +200 -0
  329. data/lib/temper/generated/models/segmented_begin.rb +212 -0
  330. data/lib/temper/generated/models/segmented_begin_response.rb +247 -0
  331. data/lib/temper/generated/models/shape_declare_request.rb +315 -0
  332. data/lib/temper/generated/models/shape_emptiness.rb +42 -0
  333. data/lib/temper/generated/models/shape_view.rb +438 -0
  334. data/lib/temper/generated/models/share_context_outcome.rb +218 -0
  335. data/lib/temper/generated/models/share_context_request.rb +166 -0
  336. data/lib/temper/generated/models/slack_disconnect_request.rb +166 -0
  337. data/lib/temper/generated/models/slack_disconnect_response.rb +168 -0
  338. data/lib/temper/generated/models/slack_disconnected_principal.rb +269 -0
  339. data/lib/temper/generated/models/slice_request.rb +216 -0
  340. data/lib/temper/generated/models/sort_order.rb +40 -0
  341. data/lib/temper/generated/models/stage_disposition.rb +42 -0
  342. data/lib/temper/generated/models/stage_input.rb +105 -0
  343. data/lib/temper/generated/models/stage_input_one_of.rb +241 -0
  344. data/lib/temper/generated/models/stage_input_one_of1.rb +253 -0
  345. data/lib/temper/generated/models/stage_input_trace.rb +241 -0
  346. data/lib/temper/generated/models/stage_node.rb +105 -0
  347. data/lib/temper/generated/models/stage_output.rb +105 -0
  348. data/lib/temper/generated/models/stage_output_one_of.rb +217 -0
  349. data/lib/temper/generated/models/stage_output_one_of1.rb +217 -0
  350. data/lib/temper/generated/models/stage_relation.rb +40 -0
  351. data/lib/temper/generated/models/stage_result.rb +423 -0
  352. data/lib/temper/generated/models/stage_trace.rb +451 -0
  353. data/lib/temper/generated/models/standing.rb +43 -0
  354. data/lib/temper/generated/models/standing_shape.rb +355 -0
  355. data/lib/temper/generated/models/subscription.rb +267 -0
  356. data/lib/temper/generated/models/subscription_override.rb +193 -0
  357. data/lib/temper/generated/models/system_access_details.rb +206 -0
  358. data/lib/temper/generated/models/team_create_request.rb +217 -0
  359. data/lib/temper/generated/models/team_detail.rb +313 -0
  360. data/lib/temper/generated/models/team_invitation.rb +406 -0
  361. data/lib/temper/generated/models/team_member_detail.rb +265 -0
  362. data/lib/temper/generated/models/team_member_row.rb +265 -0
  363. data/lib/temper/generated/models/team_member_source.rb +40 -0
  364. data/lib/temper/generated/models/team_role.rb +42 -0
  365. data/lib/temper/generated/models/team_row.rb +287 -0
  366. data/lib/temper/generated/models/team_update_request.rb +159 -0
  367. data/lib/temper/generated/models/territory.rb +298 -0
  368. data/lib/temper/generated/models/territory_kind.rb +41 -0
  369. data/lib/temper/generated/models/territory_overview.rb +223 -0
  370. data/lib/temper/generated/models/unbind_team_outcome.rb +218 -0
  371. data/lib/temper/generated/models/unrecognized_standing.rb +215 -0
  372. data/lib/temper/generated/models/unshare_context_outcome.rb +218 -0
  373. data/lib/temper/generated/models/vault_config.rb +174 -0
  374. data/lib/temper/generated/models/via_entry.rb +305 -0
  375. data/lib/temper/generated/models/wide_arm.rb +252 -0
  376. data/lib/temper/generated/models/wide_hit.rb +193 -0
  377. data/lib/temper/generated/version.rb +15 -0
  378. data/lib/temper/generated.rb +402 -0
  379. data/lib/temper/refs.rb +36 -0
  380. data/lib/temper/resources.rb +68 -0
  381. data/lib/temper/validate.rb +127 -0
  382. data/lib/temper/version.rb +11 -0
  383. data/lib/temper.rb +47 -0
  384. metadata +525 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 053faaf3ac47a6d158e0b6b01f1ee9b676721480efdb0d37da4a5a78c4852d13
4
+ data.tar.gz: 916b5ba30ee421ec644905e3dedafb900c6189536fe0afd3b1bf8fa561584f7e
5
+ SHA512:
6
+ metadata.gz: 7ee3400fe23a21d1ed53d766001502080c5c01b719a0b40602c8205f83ea7ba612b5c855fb3264955784c238df67e94505e27fb89d2b7cd1b1d4b0f142cc9128
7
+ data.tar.gz: c92c7ad413560450bdc8801f49a6c5c52cb5140e2452b8564aee7bd9c7d072233758056025218617d63728767214e94e2b86dd7731df07096ffdb7fbcc12352c
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tasker Systems
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,291 @@
1
+ # temper-rb
2
+
3
+ A pure-Ruby SDK for the [Temper](https://temperkb.io) knowledge-base API.
4
+
5
+ There is no native extension: one source gem, no compiler on the install box, no
6
+ platform matrix. The client core is generated from the API's `openapi.json` and
7
+ committed, so building and testing this gem needs neither Docker nor a JVM.
8
+
9
+ > **The integration how-to lives in the repo:**
10
+ > [docs/sdks/temper-rb.md](https://github.com/tasker-systems/temper/blob/main/docs/sdks/temper-rb.md).
11
+ > It covers the two callers, both machine-credential mint paths, the token
12
+ > lifecycle, attribution across the enqueue boundary, the error taxonomy, and
13
+ > going live. This README is the quickstart.
14
+
15
+ ## Install
16
+
17
+ ```ruby
18
+ gem 'temper-rb'
19
+ ```
20
+
21
+ Ruby >= 3.1.
22
+
23
+ ## Configure
24
+
25
+ ```ruby
26
+ Temper.configure do |c|
27
+ c.base_url = ENV.fetch('TEMPER_API_URL')
28
+ c.device_id = ENV['TEMPER_DEVICE_ID'] # optional; sets X-Temper-Device-Id
29
+ end
30
+ ```
31
+
32
+ The connection is **process-global**. The **token is per call**. Constructing a
33
+ `Temper::Client` does no I/O, so build one per request if you like.
34
+
35
+ ## Puma — a token the caller already holds
36
+
37
+ ```ruby
38
+ client = Temper::Client.new(
39
+ credentials: Temper::Credentials::BearerToken.new(session_token))
40
+
41
+ client.resources.create(
42
+ title: 'Postmortem', context_ref: '@dana/incidents',
43
+ doc_type_name: 'note', content: markdown,
44
+ act: Temper::Act.new(confidence: :probable, reasoning: 'summarised the incident'))
45
+ ```
46
+
47
+ A `BearerToken` does no I/O and **cannot refresh** — `refresh!` raises. A user's
48
+ token is not the app's to re-mint.
49
+
50
+ `Temper::Act` refuses to be built with `reasoning`, `rationale`, `persona`, or
51
+ `model` unless you also give `confidence` — the server would reject it with a
52
+ 400, so the gem rejects it locally instead.
53
+
54
+ ## Sidekiq — a machine principal
55
+
56
+ ```ruby
57
+ CREDENTIALS = Temper::Credentials::ClientCredentials.new(
58
+ token_url: ENV.fetch('TEMPER_M2M_TOKEN_URL'),
59
+ client_id: ENV.fetch('TEMPER_M2M_CLIENT_ID'),
60
+ client_secret: ENV.fetch('TEMPER_M2M_CLIENT_SECRET'),
61
+ audience: ENV['TEMPER_M2M_AUDIENCE']) # Auth0 only — omit for temper-issued
62
+ ```
63
+
64
+ It caches the token until 60 seconds before its absolute expiry, mints under a
65
+ mutex (Puma threads race a cold cache), and re-mints once on a 401 — because a job
66
+ that holds a token across a long unit of work can outlive it, and
67
+ refresh-ahead-of-expiry alone does not save you there.
68
+
69
+ ### Two mint paths
70
+
71
+ The token request is form-encoded on both (RFC 6749 §4). Only the config differs.
72
+
73
+ | | Auth0-issued (`temper admin machine provision`) | Temper-issued (`temper admin machine issue`) |
74
+ |---|---|---|
75
+ | `client_id` | your Auth0 M2M app's client id | minted by temper, prefixed `tmpr_` |
76
+ | `client_secret` | from Auth0 | printed **once** at `issue` |
77
+ | `token_url` | your Auth0 tenant's `/oauth/token` | **your own instance's** `/oauth/token` |
78
+ | `audience` | **required** — must equal the API's `AUTH_AUDIENCE` | **omit it** |
79
+
80
+ Temper's own authorization server mints with its server-side `AS_AUDIENCE` and
81
+ ignores a request-supplied one, so the SDK leaves `audience` off the wire entirely
82
+ rather than sending an empty string.
83
+
84
+ ## Correlation across the enqueue boundary
85
+
86
+ The Puma request writes as the signed-in user; the Sidekiq job it enqueues writes
87
+ as the **machine profile**. Two authors, honestly — the machine really did make the
88
+ second write. A correlation id stitches them together in the event ledger.
89
+
90
+ ```ruby
91
+ correlation = SecureRandom.uuid
92
+ PostmortemJob.perform_async(correlation)
93
+ # ...and in the worker:
94
+ act = Temper::Act.new(confidence: :probable, correlation: correlation)
95
+ ```
96
+
97
+ Correlation is provenance, never authorization. Nothing gates on it, and an act
98
+ that supplies none self-roots to its own event id — so you may always omit it.
99
+
100
+ ## Errors
101
+
102
+ ```
103
+ Temper::Error
104
+ ├─ Temper::TransientError # let it escape → Sidekiq retries
105
+ │ ├─ RateLimited (429, #retry_after)
106
+ │ ├─ ServerError (5xx)
107
+ │ └─ ConnectionError (timeout / refused)
108
+ └─ Temper::PermanentError # rescue it → dead-letter
109
+ ├─ Unauthorized (401)
110
+ ├─ Forbidden (403)
111
+ │ └─ SystemAccessRequired
112
+ ├─ NotFound (404)
113
+ ├─ Conflict (409)
114
+ └─ BadRequest (400 / 422)
115
+ ```
116
+
117
+ Every exception carries `#status`, `#code`, `#message`, and `#details`.
118
+
119
+ `SystemAccessRequired` adds `#refusal` — a **typed** reason the server refused,
120
+ which is what lets a worker tell "never granted" from "granted and then revoked"
121
+ without matching on the message string:
122
+
123
+ ```ruby
124
+ rescue Temper::SystemAccessRequired => e
125
+ case e.refusal
126
+ when Temper::Generated::Denied then request_access! # never granted — ask
127
+ when Temper::Generated::Requested then wait # asked, pending review
128
+ when Temper::Generated::Revoked then alert_operator! # had it, lost it
129
+ else log.warn("refused: #{e.refusal_kind}") # a reason newer than this gem
130
+ end
131
+ ```
132
+
133
+ Data-bearing refusals carry their payload: an `IllegalTransition` names the `act`
134
+ it refused and the standing it refused it `from`. `#refusal` is `nil` when the
135
+ reason is one this gem was not generated against — `#refusal_kind` still returns
136
+ the name the server used, so an unfamiliar refusal is logged rather than lost.
137
+
138
+ The split is load-bearing, not decorative: Sidekiq retries a job whose exception
139
+ escapes, so a 409 classified transient would spin forever and a 503 classified
140
+ permanent would be silently dropped.
141
+
142
+ Idempotent reads retry three times on 5xx and transport failures. **Writes are
143
+ never auto-retried.** The SDK classifies; it does not decide to re-submit.
144
+
145
+ ## Composition bounds raise before the request `[2026-08-28]`
146
+
147
+ `/api/query`'s contract publishes ceilings on what one composition may declare, and the
148
+ generated models enforce them in their attribute writers — which `initialize` calls — so
149
+ these raise `ArgumentError` locally rather than returning a `BadRequest` with a typed
150
+ refusal. The writers are **not** gated on `client_side_validation`, so this cannot be
151
+ switched off.
152
+
153
+ | field | ceiling |
154
+ |---|---|
155
+ | `Composition#stages` | 64 |
156
+ | `Intention#query` | 4096 |
157
+ | `IdSet#ids` | 256 |
158
+ | `ResourceFilter#doc_type` / `#tags`, `EdgeFilter#labels` | 256 |
159
+
160
+ **This is a behaviour change for code that already builds large plans**: a 300-id `IdSet`
161
+ used to construct fine and reach the server. It now raises before any HTTP call.
162
+
163
+ **The gem counts characters; the server counts bytes.** A 4096-character CJK question is
164
+ 8192 bytes — it constructs cleanly here and is refused server-side as `intention_too_long`.
165
+ The skew is one-directional (a UTF-8 string is never fewer bytes than characters), so the
166
+ gem can only under-enforce, never refuse something the server would have run.
167
+
168
+ The per-stage predicate and probe caps and the aggregate embed budget
169
+ (`intention_budget_exceeded`) are deliberately not enforced here — neither is a contract
170
+ fact — and arrive as refusals.
171
+
172
+
173
+ ## Going live
174
+
175
+ Authentication is not authorization. A valid M2M token does **not** get you in on
176
+ its own: temper keeps a registration allowlist, so your `client_id` must be
177
+ registered before your first call. An unregistered (or revoked) client
178
+ authenticates cleanly at its issuer and is then rejected with a terminal
179
+ `Unauthorized` — `client 'X' is not registered with this instance` — which the SDK
180
+ classifies as a `PermanentError` (a Sidekiq worker dead-letters it rather than
181
+ retrying). Registered but un-granted, you then get a `SystemAccessRequired` 403.
182
+ Those are the two walls, in that order.
183
+
184
+ Registration and reach happen in one command, on whichever mint path you chose:
185
+
186
+ ```bash
187
+ # Auth0-issued: register the M2M application you already created
188
+ temper admin machine provision \
189
+ --client-id "$TEMPER_M2M_CLIENT_ID" --label "acme-worker" \
190
+ --owner-team acme-eng --team acme-eng:member --cogmap <map-ref>
191
+
192
+ # Temper-issued: temper mints the client id and secret; the secret prints once
193
+ temper admin machine issue \
194
+ --label "acme-worker" \
195
+ --owner-team acme-eng --team acme-eng:member --cogmap <map-ref>
196
+ ```
197
+
198
+ Each `--team` gives **team membership** for read reach; each `--cogmap` applies a
199
+ **cogmap write grant**. Both are repeatable — reach is plural and explicit, and is
200
+ never inferred from `--owner-team` (which records the machine's owner only).
201
+
202
+ This need not be an operator ticket: minting is authorized for a system admin **or
203
+ the owner of the team that will own the machine**, so a team owner can register
204
+ their own team's machine. A teamless machine is admin-only.
205
+
206
+ **Rotation.** `temper admin machine rotate-secret` rolls a temper-issued **secret**
207
+ (same `client_id`), keeping the previous one valid for a grace window while you
208
+ redeploy the app with the new secret. `temper admin machine rebind` is a different
209
+ operation: a **new `client_id`** bound to the same agent profile, for rotating the
210
+ Auth0 application behind a machine — and it is system-admin only. Rotating an Auth0
211
+ *secret* needs no temper action at all.
212
+
213
+ See
214
+ [docs/guides/machine-credentials.md](https://github.com/tasker-systems/temper/blob/main/docs/guides/machine-credentials.md)
215
+ for the operator's side.
216
+
217
+ Assert it worked at boot rather than discovering it on the first write:
218
+
219
+ ```ruby
220
+ Temper::Client.new(credentials: CREDENTIALS).whoami
221
+ ```
222
+
223
+ An unregistered client surfaces as `Unauthorized` naming the client id; a
224
+ registered-but-under-granted one surfaces as `Forbidden` / `SystemAccessRequired`
225
+ naming the missing grant — both from the server's `error.details`, not a bare 4xx.
226
+
227
+ ## Forking
228
+
229
+ The connection holds sockets. Call `Temper.reset_connection!` in a forked worker:
230
+
231
+ ```ruby
232
+ # config/puma.rb
233
+ on_worker_boot { Temper.reset_connection! }
234
+
235
+ # config/initializers/sidekiq.rb
236
+ Sidekiq.configure_server { |_| Temper.reset_connection! }
237
+ ```
238
+
239
+ Strictly speaking the sockets are already safe: `connection_pool` (>= 2.4, which
240
+ `net-http-persistent` pools through) drops them from a `Process._fork` hook, and
241
+ this gem's test suite proves a forked child opens its own socket. The hooks above
242
+ clear *this gem's* memoized client rather than relying on a transitive
243
+ dependency's default. Keep them.
244
+
245
+ ## Addressing
246
+
247
+ Resources are addressed by **ref**: a bare UUID, or the decorated
248
+ `sluggify(title)-<uuid>` form. Resolution is trailing-UUID-only, so a stale slug
249
+ half is harmless.
250
+
251
+ ```ruby
252
+ client.resources.show('p4-design-the-gem-019f4912-3f20-7fd3-814f-13a5ddbe3cd7')
253
+ client.resources.show('019f4912-3f20-7fd3-814f-13a5ddbe3cd7') # identical
254
+ ```
255
+
256
+ `Temper.parse_ref` is available directly, and never touches the network.
257
+
258
+ ## Cognitive maps
259
+
260
+ The SDK authors into a map incrementally — `cognitive_maps.author` (ingest with
261
+ `home_cogmap_id`), `assert_relationship`, and `set_facet` — all paths where the
262
+ server chunks and embeds for you.
263
+
264
+ **Bulk reconcile is not exposed.** `PUT /api/cognitive-maps/{id}` takes a
265
+ pre-embedded desired-state manifest: its `chunks_packed` is a required,
266
+ client-computed 768-dimension BGE embedding, carried verbatim with no server-side
267
+ fallback. Ruby has no embedder, so that path is physically out of reach. It is a
268
+ CLI operator's job, not a Rails request's. If you truly need it, reach
269
+ `Temper::Generated::CognitiveMapsApi#reconcile` and pack the chunks yourself.
270
+
271
+ ## Versioning
272
+
273
+ `Temper::VERSION` is the gem's own SemVer. `Temper::CONTRACT_VERSION` names the
274
+ `openapi.json` it was generated against. They answer different questions and are
275
+ not forced to agree.
276
+
277
+ ## Development
278
+
279
+ ```bash
280
+ bundle install
281
+ bundle exec rake # rubocop + rspec
282
+ bundle exec rake generate # regenerate lib/temper/generated/** (needs Docker)
283
+ bundle exec rake drift # fail if the committed core drifts from the contract
284
+ ```
285
+
286
+ `rake generate` is the only writer of `lib/temper/generated/**`. Never hand-edit
287
+ that tree; the hand-written skin lives beside it, in `lib/temper/*.rb`.
288
+
289
+ ## License
290
+
291
+ MIT.
data/lib/temper/act.rb ADDED
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Temper
4
+ # Act context for a write. Optional on every call.
5
+ #
6
+ # The constructor invariant mirrors ActInput::into_act_context: Rust's
7
+ # AgentAuthorship.confidence is non-Option, so authorship without confidence is
8
+ # a 400. Rejecting it here is the parse-don't-validate answer -- an invalid Act
9
+ # cannot be constructed, so no call site can send one.
10
+ #
11
+ # `correlation` and `invocation` are exempt: correlation is provenance, never
12
+ # authorship, and an act with no supplied correlation self-roots to its own
13
+ # event id. Nothing gates on it, so the gem may always omit it.
14
+ class Act
15
+ AUTHORSHIP_FIELDS = %i[reasoning rationale persona model].freeze
16
+
17
+ def initialize(confidence: nil, reasoning: nil, rationale: nil, persona: nil, model: nil,
18
+ correlation: nil, invocation: nil)
19
+ authorship = { reasoning: reasoning, rationale: rationale, persona: persona, model: model }
20
+ require_confidence!(confidence, authorship)
21
+
22
+ @fields = authorship.merge(
23
+ confidence: confidence&.to_s,
24
+ correlation_id: correlation,
25
+ invocation_id: invocation
26
+ ).compact.freeze
27
+ end
28
+
29
+ # Symbol-keyed, nils omitted: the server distinguishes an absent key from null.
30
+ # These are the seven ActInput wire keys, which flatten into ~30 write bodies
31
+ # and onto the query string of DELETE /api/resources/{id}.
32
+ def to_h
33
+ @fields.dup
34
+ end
35
+
36
+ private
37
+
38
+ def require_confidence!(confidence, authorship)
39
+ return unless confidence.nil?
40
+
41
+ supplied = authorship.compact.keys
42
+ return if supplied.empty?
43
+
44
+ raise ArgumentError, "Temper::Act requires `confidence:` when supplying #{supplied.join(', ')}"
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Temper
4
+ # A cheap façade over the process-global connection. Holds a credential and
5
+ # nothing else; constructing one does no I/O, so a Puma request can build one
6
+ # per user and a Sidekiq process can memoize one.
7
+ class Client
8
+ MAX_READ_ATTEMPTS = 3
9
+ # 200ms, 400ms -- mirroring MAX_ATTEMPTS and the backoff in
10
+ # crates/temper-client/src/http.rs.
11
+ DEFAULT_BACKOFF = ->(attempt) { sleep(0.2 * (2**(attempt - 1))) }
12
+
13
+ def initialize(credentials:, backoff: DEFAULT_BACKOFF)
14
+ @credentials = credentials
15
+ @backoff = backoff
16
+ end
17
+
18
+ # Assert the machine profile resolved, and report what it can reach, rather
19
+ # than discovering it on the first write.
20
+ #
21
+ # Authentication is not authorization. A minted M2M token does not even yield a
22
+ # profile on its own: the client_id must already be registered (lookup-or-401 --
23
+ # there is no JIT-create branch), and then, without a cogmap write grant and team
24
+ # membership, every call authenticates cleanly and 403s.
25
+ def whoami
26
+ call(idempotent: true) { |api| Generated::ProfileApi.new(api).get_profile }
27
+ end
28
+
29
+ def resources
30
+ @resources ||= Resources.new(self)
31
+ end
32
+
33
+ def contexts
34
+ @contexts ||= Contexts.new(self)
35
+ end
36
+
37
+ def cognitive_maps
38
+ @cognitive_maps ||= CognitiveMaps.new(self)
39
+ end
40
+
41
+ # SearchParams names the field `query`, not `q`.
42
+ def search(query, **opts)
43
+ params = Generated::SearchParams.new({ query: query }.merge(opts))
44
+ call(idempotent: true) { |api| Generated::SearchApi.new(api).search(params) }
45
+ end
46
+
47
+ def graph
48
+ Generated::GraphApi.new(Temper.api_client)
49
+ end
50
+
51
+ # The one seam every surface module goes through.
52
+ #
53
+ # idempotent: true => a safe method. 5xx and transport failures retry.
54
+ # idempotent: false => a write. NEVER auto-retried.
55
+ #
56
+ # A 401 is repaired once, for reads and writes alike: re-authenticating is not
57
+ # re-submitting. BearerToken#refresh! raises, so a bearer caller makes exactly
58
+ # one request and the Unauthorized propagates out of refresh! itself.
59
+ def call(idempotent: false, &block)
60
+ attempt = 0
61
+ reminted = false
62
+
63
+ begin
64
+ attempt += 1
65
+ Temper.with_token(@credentials.token) { block.call(Temper.api_client) }
66
+ rescue Generated::ApiError => e
67
+ error = ErrorMapper.call(e)
68
+
69
+ if repair_credentials?(error, reminted)
70
+ reminted = true
71
+ retry
72
+ end
73
+
74
+ raise error unless retryable_read?(error, idempotent, attempt)
75
+
76
+ @backoff.call(attempt)
77
+ retry
78
+ end
79
+ end
80
+
81
+ private
82
+
83
+ # BearerToken#refresh! raises Unauthorized, so a bearer caller never reaches
84
+ # the retry -- the raise propagates straight out of refresh!.
85
+ def repair_credentials?(error, reminted)
86
+ return false unless error.is_a?(Unauthorized) && !reminted
87
+
88
+ @credentials.refresh!
89
+ true
90
+ end
91
+
92
+ def retryable_read?(error, idempotent, attempt)
93
+ idempotent && error.is_a?(TransientError) && attempt < MAX_READ_ATTEMPTS
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Temper
4
+ # Incremental cognitive-map authoring (D9).
5
+ #
6
+ # Every path here is server-recompute: the server chunks and embeds. Bulk
7
+ # reconcile (PUT /api/cognitive-maps/{id}) is deliberately absent -- its
8
+ # ReconcileEntry.chunks_packed is a required, PRE-EMBEDDED String, carried
9
+ # verbatim with no server-side ONNX fallback, so a Ruby client cannot physically
10
+ # reach it without a 768-dim BGE embedder. It is a CLI operator's job, not a
11
+ # Rails request's. Reach Generated::CognitiveMapsApi#reconcile directly if you
12
+ # hand-pack chunks.
13
+ class CognitiveMaps
14
+ DEFAULT_POLARITY = 'forward'
15
+
16
+ def initialize(client)
17
+ @client = client
18
+ end
19
+
20
+ # POST /api/cognitive-maps -> 200 CreateCogmapOutcome.
21
+ #
22
+ # Genesis takes an Option<ReconcileTelos>, so a charter-less map is creatable
23
+ # -- but CreateCogmapRequest still requires `telos_title`. Charter-less is not
24
+ # title-less. CreateCogmapRequest carries no act keys.
25
+ def create(name:, telos_title:, telos: nil, cogmap_id: nil, telos_resource_id: nil)
26
+ attrs = { name: name, telos_title: telos_title }
27
+ attrs[:telos] = telos unless telos.nil?
28
+ attrs[:cogmap_id] = cogmap_id unless cogmap_id.nil?
29
+ attrs[:telos_resource_id] = telos_resource_id unless telos_resource_id.nil?
30
+
31
+ body = Generated::CreateCogmapRequest.new(attrs)
32
+ @client.call { |api| Generated::CognitiveMapsApi.new(api).genesis(body) }
33
+ end
34
+
35
+ # A map node is a NEW resource that distills from its sources; ingest with
36
+ # home_cogmap_id is how it is born. The server chunks and embeds.
37
+ def author(cogmap_ref, title:, content:, context_ref:, doc_type_name:, act: nil, **opts)
38
+ @client.resources.create(
39
+ title: title, context_ref: context_ref, doc_type_name: doc_type_name,
40
+ content: content, act: act, home_cogmap_id: Temper.parse_ref(cogmap_ref), **opts
41
+ )
42
+ end
43
+
44
+ # POST /api/relationships (not /api/relationships/assert). The contract requires
45
+ # all of source, target, edge_kind, polarity, label, weight; the seven act keys
46
+ # flatten on, as they do on IngestPayload.
47
+ #
48
+ # edge_kind is one of express, contains, leads_to, near.
49
+ def assert_relationship(source:, target:, edge_kind:, label:, weight:,
50
+ polarity: DEFAULT_POLARITY, act: nil)
51
+ body = Generated::AssertRelationshipRequest.new(
52
+ { source: Temper.parse_ref(source), target: Temper.parse_ref(target),
53
+ edge_kind: edge_kind, polarity: polarity, label: label, weight: weight }
54
+ .merge(act_hash(act))
55
+ )
56
+ @client.call { |api| Generated::RelationshipsApi.new(api).assert(body) }
57
+ end
58
+
59
+ # POST /api/facets (not /api/facets/set). `values` is plural, and is the
60
+ # facet's typed value payload.
61
+ def set_facet(resource:, values:, weight: nil, act: nil)
62
+ attrs = { resource: Temper.parse_ref(resource), values: values }
63
+ attrs[:weight] = weight unless weight.nil?
64
+
65
+ body = Generated::FacetSetRequest.new(attrs.merge(act_hash(act)))
66
+ @client.call { |api| Generated::FacetsApi.new(api).set_facet(body) }
67
+ end
68
+
69
+ private
70
+
71
+ def act_hash(act)
72
+ act.nil? ? {} : act.to_h
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+ require 'faraday/gzip'
5
+ require 'faraday/net_http_persistent'
6
+ require 'uri'
7
+
8
+ module Temper
9
+ # Thread.current[] is FIBER-local in Ruby (Thread#thread_variable_get is the
10
+ # thread-local one). Fiber[] would read better but arrived in 3.2, and the
11
+ # gem's floor is 3.1.
12
+ TOKEN_KEY = :temper_access_token
13
+ private_constant :TOKEN_KEY
14
+
15
+ class << self
16
+ # One ApiClient per process => one Faraday connection => one
17
+ # net-http-persistent per-thread pool.
18
+ #
19
+ # A fresh Configuration + ApiClient per request is the obvious fix for the
20
+ # generated singletons' single shared access_token, and it is a trap: fresh
21
+ # client, fresh connection, TLS handshake per request. Instead the connection
22
+ # is process-global and the TOKEN is call-scoped, via access_token_getter.
23
+ def api_client
24
+ connection_mutex.synchronize { @api_client ||= build_api_client }
25
+ end
26
+
27
+ # Call from Puma's on_worker_boot and from Sidekiq.configure_server, so a
28
+ # forked worker never inherits its parent's sockets.
29
+ def reset_connection!
30
+ connection_mutex.synchronize { @api_client = nil }
31
+ nil
32
+ end
33
+
34
+ def current_token
35
+ Thread.current[TOKEN_KEY]
36
+ end
37
+
38
+ def with_token(token)
39
+ previous = Thread.current[TOKEN_KEY]
40
+ Thread.current[TOKEN_KEY] = token
41
+ yield
42
+ ensure
43
+ Thread.current[TOKEN_KEY] = previous
44
+ end
45
+
46
+ private
47
+
48
+ def connection_mutex
49
+ @connection_mutex ||= Mutex.new
50
+ end
51
+
52
+ def build_api_client
53
+ generated = build_generated_config
54
+ Generated::ApiClient.new(generated).tap do |client|
55
+ client.default_headers['X-Temper-Surface'] = 'sdk'
56
+ client.default_headers['X-Temper-Device-Id'] = config.device_id if config.device_id
57
+ end
58
+ end
59
+
60
+ def build_generated_config
61
+ Generated::Configuration.new.tap do |c|
62
+ apply_endpoint(c, base_uri)
63
+ c.access_token_getter = -> { Temper.current_token }
64
+ configure_faraday(c)
65
+ end
66
+ end
67
+
68
+ def base_uri
69
+ raise ArgumentError, 'Temper.config.base_url is not set' if config.base_url.nil?
70
+
71
+ # Every request puts the bearer token on this URL, so the scheme is
72
+ # checked where the client is built, not per request. The opt-in is
73
+ # configuration here (not a kwarg) because the gem's URL is process-wide.
74
+ Validate.require_endpoint(config.base_url, name: 'base_url',
75
+ allow_insecure_http: config.allow_insecure_http)
76
+ end
77
+
78
+ def apply_endpoint(generated_config, base)
79
+ generated_config.scheme = base.scheme
80
+ generated_config.host = host_with_port(base)
81
+ generated_config.base_path = base.path
82
+ end
83
+
84
+ # `configure_faraday_connection` REGISTERS the block; `configure_connection` is
85
+ # the invoker the generated ApiClient calls with the connection.
86
+ #
87
+ # It runs AFTER build_connection sets conn.adapter(Faraday.default_adapter), so
88
+ # setting the adapter here replaces it. An adapter set via `configure_middleware`
89
+ # runs BEFORE, and would be silently overwritten by the default -- costing a TLS
90
+ # handshake per request while nothing fails.
91
+ #
92
+ # `conn.request :gzip` installs faraday-gzip's decompression middleware. It sets
93
+ # Accept-Encoding: gzip,deflate and inflates the response in Faraday's
94
+ # on_complete -- OUTSIDE Net::HTTP. That is the whole point: the
95
+ # net_http_persistent adapter bypasses Net::HTTP's transparent gzip handling, so
96
+ # without this a `Content-Encoding: gzip` body reaches the deserializer as raw
97
+ # compressed bytes and every read returns nil (issue #446). Order is irrelevant
98
+ # -- Faraday keeps the adapter last regardless of call order -- but registering
99
+ # the request middleware before the adapter reads in stack order.
100
+ def configure_faraday(generated_config)
101
+ generated_config.configure_faraday_connection do |conn|
102
+ conn.request :gzip
103
+ conn.adapter :net_http_persistent, pool_size: 5
104
+ end
105
+ end
106
+
107
+ def host_with_port(base)
108
+ return base.host if base.port.nil? || base.port == base.default_port
109
+
110
+ "#{base.host}:#{base.port}"
111
+ end
112
+ end
113
+ end