rbek 0.2.1__py3-none-any.whl

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 (477) hide show
  1. rbek/__init__.py +0 -0
  2. rbek/adoption/__init__.py +17 -0
  3. rbek/adoption/http_adapter.py +89 -0
  4. rbek/adoption/http_listener.py +147 -0
  5. rbek/adoption/intake.py +141 -0
  6. rbek/adoption/retention.py +274 -0
  7. rbek/adoption/runtime_composition.py +56 -0
  8. rbek/adoption/service_runtime.py +16 -0
  9. rbek/adoption/service_store.py +216 -0
  10. rbek/architecture_graph/__init__.py +22 -0
  11. rbek/architecture_graph/builder.py +759 -0
  12. rbek/architecture_graph/models.py +246 -0
  13. rbek/bootstrap/__init__.py +0 -0
  14. rbek/cli/__init__.py +23 -0
  15. rbek/cli/__main__.py +183 -0
  16. rbek/cli/activation_gate_commands.py +1061 -0
  17. rbek/cli/adapter_promotion_commands.py +1479 -0
  18. rbek/cli/adoption_binding.py +90 -0
  19. rbek/cli/adoption_events.py +153 -0
  20. rbek/cli/adoption_remote_contract.py +234 -0
  21. rbek/cli/adoption_remote_sender.py +54 -0
  22. rbek/cli/adoption_remote_transport.py +53 -0
  23. rbek/cli/authorization_commands.py +458 -0
  24. rbek/cli/commands.py +219 -0
  25. rbek/cli/commercial_activation_commands.py +186 -0
  26. rbek/cli/commercial_customer_package_commands.py +113 -0
  27. rbek/cli/commercial_enforcement.py +389 -0
  28. rbek/cli/commercial_entitlement_commands.py +379 -0
  29. rbek/cli/commercial_offline_verification_commands.py +156 -0
  30. rbek/cli/context.py +32 -0
  31. rbek/cli/controlled_executable_registry.py +325 -0
  32. rbek/cli/controlled_executable_registry_producer.py +155 -0
  33. rbek/cli/controlled_executable_resolution.py +184 -0
  34. rbek/cli/customer_project_quickstart_commands.py +70 -0
  35. rbek/cli/developer_execution_commands.py +727 -0
  36. rbek/cli/developer_execution_v2.py +389 -0
  37. rbek/cli/developer_execution_v2_activation.py +527 -0
  38. rbek/cli/developer_execution_v2_authority_ref_loader.py +214 -0
  39. rbek/cli/developer_execution_v2_command_mode.py +49 -0
  40. rbek/cli/developer_execution_v2_commands.py +321 -0
  41. rbek/cli/developer_execution_v2_consumption.py +109 -0
  42. rbek/cli/developer_execution_v2_context.py +177 -0
  43. rbek/cli/developer_execution_v2_context_population.py +322 -0
  44. rbek/cli/developer_execution_v2_trusted_wiring.py +125 -0
  45. rbek/cli/dry_run_evidence_commands.py +669 -0
  46. rbek/cli/errors.py +19 -0
  47. rbek/cli/executable_descriptor_contract.py +974 -0
  48. rbek/cli/exit_codes.py +12 -0
  49. rbek/cli/filesystem_environment_loader.py +273 -0
  50. rbek/cli/filesystem_executable_descriptor_loader.py +261 -0
  51. rbek/cli/filesystem_source_admission.py +523 -0
  52. rbek/cli/legacy_main.py +86 -0
  53. rbek/cli/local_execution_adapters.py +390 -0
  54. rbek/cli/local_execution_commands.py +1608 -0
  55. rbek/cli/onboarding_commands.py +276 -0
  56. rbek/cli/output.py +66 -0
  57. rbek/cli/parser.py +154 -0
  58. rbek/cli/policy_execution_commands.py +740 -0
  59. rbek/cli/product_commands.py +934 -0
  60. rbek/cli/promoted_adapters/customer_transform/__init__.py +3 -0
  61. rbek/cli/promoted_adapters/customer_transform/adapter.py +31 -0
  62. rbek/cli/promoted_adapters/governed_action_delegation_create/adapter.py +78 -0
  63. rbek/cli/promoted_adapters/governed_action_resource_approve/adapter.py +78 -0
  64. rbek/cli/promoted_adapters/governed_action_resource_compare/adapter.py +78 -0
  65. rbek/cli/promoted_adapters/governed_action_resource_create/adapter.py +78 -0
  66. rbek/cli/promoted_adapters/governed_action_resource_read/adapter.py +78 -0
  67. rbek/cli/promoted_adapters/governed_action_resource_request/adapter.py +78 -0
  68. rbek/cli/promoted_adapters/http_json/__init__.py +1 -0
  69. rbek/cli/promoted_adapters/http_json/adapter.py +197 -0
  70. rbek/cli/promoted_adapters/integrations001d/__init__.py +3 -0
  71. rbek/cli/promoted_adapters/integrations001d/adapter.py +31 -0
  72. rbek/cli/promoted_adapters/langgraph_governed_tool/__init__.py +3 -0
  73. rbek/cli/promoted_adapters/langgraph_governed_tool/adapter.py +31 -0
  74. rbek/cli/promoted_adapters/open_meteo/__init__.py +0 -0
  75. rbek/cli/promoted_adapters/open_meteo/adapter.py +391 -0
  76. rbek/cli/promoted_adapters/test_transform/adapter.py +2 -0
  77. rbek/cli/promoted_execution_certification_commands.py +1160 -0
  78. rbek/cli/provider_adapter_projection.py +207 -0
  79. rbek/cli/receipt_sdk_commands.py +1083 -0
  80. rbek/cli/sdk_registration_commands.py +1487 -0
  81. rbek/cli/telemetry_commands.py +321 -0
  82. rbek/cli/telemetry_config.py +86 -0
  83. rbek/cli/trusted_executable_origin_composition.py +38 -0
  84. rbek/cli/trusted_executable_process_projection.py +241 -0
  85. rbek/cli/trusted_executable_registry_composition.py +245 -0
  86. rbek/cli/trusted_executable_registry_entry_projection.py +138 -0
  87. rbek/cli/trusted_live_executable_authority.py +382 -0
  88. rbek/cli/trusted_runtime_bootstrap.py +65 -0
  89. rbek/cli/trusted_runtime_composition.py +152 -0
  90. rbek/cli/trusted_runtime_configuration.py +163 -0
  91. rbek/cli/trusted_runtime_environment_source.py +371 -0
  92. rbek/cli/trusted_source_contract.py +300 -0
  93. rbek/cli/verified_execution_authority.py +490 -0
  94. rbek/cli/version.py +24 -0
  95. rbek/commercial/__init__.py +30 -0
  96. rbek/commercial/activation.py +440 -0
  97. rbek/commercial/customer_package.py +326 -0
  98. rbek/commercial/enforcement.py +169 -0
  99. rbek/commercial/entitlement.py +561 -0
  100. rbek/commercial/issuer.py +180 -0
  101. rbek/commercial/offline_verification.py +283 -0
  102. rbek/commercial/signing.py +180 -0
  103. rbek/commercial/verification.py +46 -0
  104. rbek/common/__init__.py +5 -0
  105. rbek/common/constants.py +17 -0
  106. rbek/common/filesystem.py +76 -0
  107. rbek/common/hashing.py +42 -0
  108. rbek/common/resources.py +50 -0
  109. rbek/contracts/__init__.py +27 -0
  110. rbek/contracts/adapter_capability_gate.py +83 -0
  111. rbek/contracts/adapter_integration.py +79 -0
  112. rbek/contracts/adapter_integration_audit.py +95 -0
  113. rbek/contracts/adapter_integration_envelope.py +61 -0
  114. rbek/contracts/adapter_integration_gate.py +78 -0
  115. rbek/contracts/adapter_integration_policy.py +90 -0
  116. rbek/contracts/adapter_registry.py +75 -0
  117. rbek/contracts/canonical_intake_attachment.py +37 -0
  118. rbek/contracts/canonical_intake_body.py +37 -0
  119. rbek/contracts/canonical_intake_builder.py +68 -0
  120. rbek/contracts/canonical_intake_classification_hint.py +39 -0
  121. rbek/contracts/canonical_intake_composition.py +40 -0
  122. rbek/contracts/canonical_intake_envelope.py +54 -0
  123. rbek/contracts/canonical_intake_identity.py +47 -0
  124. rbek/contracts/canonical_intake_participant.py +35 -0
  125. rbek/contracts/canonical_intake_source_metadata.py +42 -0
  126. rbek/contracts/certification/__init__.py +13 -0
  127. rbek/contracts/certification/models.py +98 -0
  128. rbek/contracts/certification/provider.py +63 -0
  129. rbek/contracts/controlled_webhook_receiver.py +74 -0
  130. rbek/contracts/controlled_webhook_replay_idempotency.py +225 -0
  131. rbek/contracts/controlled_webhook_runtime_binding.py +89 -0
  132. rbek/contracts/email_artifact_registration.py +162 -0
  133. rbek/contracts/email_capability_resolution.py +70 -0
  134. rbek/contracts/email_ingestion_batch.py +409 -0
  135. rbek/contracts/email_ingestion_checkpoint.py +206 -0
  136. rbek/contracts/email_kernel_lifecycle_decision_gate.py +84 -0
  137. rbek/contracts/email_kernel_lifecycle_handover.py +67 -0
  138. rbek/contracts/email_kernel_lifecycle_inspection.py +72 -0
  139. rbek/contracts/email_kernel_lifecycle_policy.py +90 -0
  140. rbek/contracts/email_kernel_lifecycle_transition.py +84 -0
  141. rbek/contracts/email_runtime_binding.py +70 -0
  142. rbek/contracts/email_runtime_registration.py +73 -0
  143. rbek/contracts/evidence/__init__.py +13 -0
  144. rbek/contracts/evidence/models.py +53 -0
  145. rbek/contracts/evidence/provider.py +39 -0
  146. rbek/contracts/identity/__init__.py +13 -0
  147. rbek/contracts/identity/models.py +46 -0
  148. rbek/contracts/identity/provider.py +33 -0
  149. rbek/contracts/policy/__init__.py +15 -0
  150. rbek/contracts/policy/models.py +70 -0
  151. rbek/contracts/policy/provider.py +30 -0
  152. rbek/contracts/provider_boot_envelope.py +212 -0
  153. rbek/contracts/provider_boot_lifecycle_gate.py +311 -0
  154. rbek/contracts/provider_boot_orchestration.py +250 -0
  155. rbek/contracts/provider_boot_policy.py +221 -0
  156. rbek/contracts/provider_boot_step.py +236 -0
  157. rbek/contracts/provider_dependency_graph.py +305 -0
  158. rbek/contracts/provider_dependency_lifecycle_gate.py +244 -0
  159. rbek/contracts/provider_dependency_plan.py +245 -0
  160. rbek/contracts/provider_dependency_runtime.py +128 -0
  161. rbek/contracts/provider_dependency_runtime_event.py +167 -0
  162. rbek/contracts/provider_dependency_runtime_event_recorder.py +106 -0
  163. rbek/contracts/provider_lifecycle.py +71 -0
  164. rbek/contracts/provider_lifecycle_adapter_gate.py +76 -0
  165. rbek/contracts/provider_lifecycle_envelope.py +51 -0
  166. rbek/contracts/provider_lifecycle_policy.py +123 -0
  167. rbek/contracts/provider_lifecycle_registry_gate.py +108 -0
  168. rbek/contracts/provider_lifecycle_transition.py +115 -0
  169. rbek/contracts/registry/__init__.py +13 -0
  170. rbek/contracts/registry/models.py +52 -0
  171. rbek/contracts/registry/provider.py +33 -0
  172. rbek/contracts/resend_email_pipeline_integration.py +77 -0
  173. rbek/contracts/resend_email_received_webhook_payload.py +389 -0
  174. rbek/contracts/resend_inbound_mapping.py +116 -0
  175. rbek/contracts/resend_inbound_provider.py +101 -0
  176. rbek/contracts/resend_inbound_provider_implementation.py +96 -0
  177. rbek/contracts/resend_webhook_translation.py +88 -0
  178. rbek/contracts/resend_webhook_transport.py +115 -0
  179. rbek/contracts/runtime_context/__init__.py +13 -0
  180. rbek/contracts/runtime_context/models.py +51 -0
  181. rbek/contracts/runtime_context/provider.py +33 -0
  182. rbek/contracts/webhook_secret_reference.py +99 -0
  183. rbek/contracts/webhook_signature_authority.py +176 -0
  184. rbek/developer/__init__.py +26 -0
  185. rbek/developer/action.py +369 -0
  186. rbek/developer/models.py +24 -0
  187. rbek/developer/policy.py +245 -0
  188. rbek/document/__init__.py +340 -0
  189. rbek/document/bank_statement_document.py +777 -0
  190. rbek/document/bank_statement_intelligence.py +289 -0
  191. rbek/document/bank_statement_service.py +56 -0
  192. rbek/document/business_document.py +382 -0
  193. rbek/document/canonical_document.py +382 -0
  194. rbek/document/canonical_document_handoff.py +230 -0
  195. rbek/document/classification.py +721 -0
  196. rbek/document/classification_profile_resolution.py +187 -0
  197. rbek/document/controlled_output.py +361 -0
  198. rbek/document/credit_note_document.py +361 -0
  199. rbek/document/credit_note_intelligence.py +746 -0
  200. rbek/document/credit_note_service.py +61 -0
  201. rbek/document/deduplication.py +579 -0
  202. rbek/document/enrichment.py +657 -0
  203. rbek/document/existing_ingestion_adapter.py +367 -0
  204. rbek/document/extraction.py +566 -0
  205. rbek/document/extraction_profiles.py +462 -0
  206. rbek/document/field_extraction_provider.py +637 -0
  207. rbek/document/file_analysis_service.py +489 -0
  208. rbek/document/file_bank_statement_service.py +177 -0
  209. rbek/document/file_credit_note_service.py +45 -0
  210. rbek/document/file_invoice_service.py +214 -0
  211. rbek/document/file_purchase_order_service.py +31 -0
  212. rbek/document/file_receipt_service.py +194 -0
  213. rbek/document/generic_document_http.py +256 -0
  214. rbek/document/http_api.py +1379 -0
  215. rbek/document/http_server.py +114 -0
  216. rbek/document/invoice_document.py +608 -0
  217. rbek/document/invoice_intelligence.py +310 -0
  218. rbek/document/invoice_service.py +77 -0
  219. rbek/document/native_text.py +358 -0
  220. rbek/document/pdf_native_text.py +401 -0
  221. rbek/document/pipeline.py +342 -0
  222. rbek/document/purchase_order_document.py +251 -0
  223. rbek/document/purchase_order_intelligence.py +581 -0
  224. rbek/document/purchase_order_invoice_matching.py +368 -0
  225. rbek/document/purchase_order_service.py +23 -0
  226. rbek/document/receipt_document.py +735 -0
  227. rbek/document/receipt_intelligence.py +292 -0
  228. rbek/document/receipt_service.py +63 -0
  229. rbek/document/reconciliation.py +467 -0
  230. rbek/document/tenant_key_admin.py +532 -0
  231. rbek/document/validation.py +592 -0
  232. rbek/email/__init__.py +1 -0
  233. rbek/email/accounts_payable_route_worker_service_entrypoint.py +251 -0
  234. rbek/email/bank_ap_paid_authorization_persistence.py +941 -0
  235. rbek/email/bank_ap_paid_authorization_runtime.py +264 -0
  236. rbek/email/bank_ap_paid_state_authority.py +577 -0
  237. rbek/email/bank_ap_paid_state_promotion.py +1177 -0
  238. rbek/email/bank_ap_paid_state_read_model.py +1021 -0
  239. rbek/email/bank_ap_payment_eligibility.py +581 -0
  240. rbek/email/bank_ap_payment_eligibility_persistence.py +1118 -0
  241. rbek/email/bank_ap_payment_eligibility_runtime.py +243 -0
  242. rbek/email/bank_ap_reconciliation_activation.py +809 -0
  243. rbek/email/bank_ap_reconciliation_contract.py +159 -0
  244. rbek/email/bank_ap_reconciliation_engine.py +828 -0
  245. rbek/email/bank_ap_reconciliation_persistence.py +1040 -0
  246. rbek/email/bank_ap_reconciliation_runtime.py +877 -0
  247. rbek/email/bank_statement_cash_truth_processor.py +1125 -0
  248. rbek/email/bank_statement_route_worker_service_entrypoint.py +235 -0
  249. rbek/email/canonical_inbound_materialization.py +816 -0
  250. rbek/email/capability_resolution.py +57 -0
  251. rbek/email/controlled_execution_provider.py +318 -0
  252. rbek/email/controlled_execution_registration.py +69 -0
  253. rbek/email/controlled_webhook_concrete_runtime_dependencies.py +342 -0
  254. rbek/email/controlled_webhook_operational_application.py +647 -0
  255. rbek/email/controlled_webhook_persistence_runtime_composition.py +209 -0
  256. rbek/email/controlled_webhook_receiver.py +287 -0
  257. rbek/email/controlled_webhook_replay_idempotency.py +886 -0
  258. rbek/email/controlled_webhook_runtime_binding.py +456 -0
  259. rbek/email/controlled_webhook_service_entrypoint.py +414 -0
  260. rbek/email/document_classification_routing.py +815 -0
  261. rbek/email/document_ingestion_bridge.py +1290 -0
  262. rbek/email/document_route_consumer.py +287 -0
  263. rbek/email/document_route_processor_runtime.py +297 -0
  264. rbek/email/document_route_processors.py +1868 -0
  265. rbek/email/document_route_work_handoff.py +295 -0
  266. rbek/email/document_route_worker.py +1597 -0
  267. rbek/email/document_route_worker_service_entrypoint.py +233 -0
  268. rbek/email/invoice_accounts_payable_processor.py +1595 -0
  269. rbek/email/kernel_lifecycle_decision_gate.py +50 -0
  270. rbek/email/kernel_lifecycle_handover.py +38 -0
  271. rbek/email/kernel_lifecycle_inspection.py +51 -0
  272. rbek/email/kernel_lifecycle_policy.py +96 -0
  273. rbek/email/kernel_lifecycle_transition.py +89 -0
  274. rbek/email/receipt_route_worker_service_entrypoint.py +251 -0
  275. rbek/email/receipt_semantic_processor.py +1317 -0
  276. rbek/email/resend_email_pipeline.py +74 -0
  277. rbek/email/resend_inbound_mapping.py +80 -0
  278. rbek/email/resend_inbound_provider.py +78 -0
  279. rbek/email/resend_raw_webhook_translation_request_mapper.py +305 -0
  280. rbek/email/resend_received_content_retrieval.py +1127 -0
  281. rbek/email/resend_webhook_translation.py +57 -0
  282. rbek/email/rms_newhotel_document_processor.py +381 -0
  283. rbek/email/rms_newhotel_route_worker_service_entrypoint.py +233 -0
  284. rbek/email/runtime_binding_declaration.py +67 -0
  285. rbek/email/runtime_registration.py +72 -0
  286. rbek/email/sqlite_controlled_webhook_idempotency_store.py +828 -0
  287. rbek/email/svix_webhook_signature_backend.py +81 -0
  288. rbek/email/treasury_ap_application_surface.py +466 -0
  289. rbek/email/treasury_ap_http_application.py +594 -0
  290. rbek/email/treasury_ap_http_service_entrypoint.py +214 -0
  291. rbek/email/treasury_ap_payment_state_integration.py +563 -0
  292. rbek/email/webhook_signature_backend.py +37 -0
  293. rbek/email/webhook_signature_verifier.py +169 -0
  294. rbek/intake/__init__.py +1 -0
  295. rbek/intake/canonical_intake_builder.py +66 -0
  296. rbek/integrations/__init__.py +5 -0
  297. rbek/integrations/asteria_public_authority_resolver.py +1691 -0
  298. rbek/integrations/framework_execution.py +226 -0
  299. rbek/integrations/synthworld_external_adapter.py +537 -0
  300. rbek/kernel/__init__.py +0 -0
  301. rbek/kernel/capability_resolver.py +90 -0
  302. rbek/kernel/certification_capability.py +85 -0
  303. rbek/kernel/evidence_binding.py +123 -0
  304. rbek/kernel/policy_evaluation.py +92 -0
  305. rbek/kernel/provider_binding_registry.py +81 -0
  306. rbek/kernel/runtime_execution_context.py +101 -0
  307. rbek/manifest/__init__.py +3 -0
  308. rbek/manifest/constants.py +8 -0
  309. rbek/manifest/exceptions.py +14 -0
  310. rbek/manifest/models.py +26 -0
  311. rbek/platform_api/__init__.py +13 -0
  312. rbek/platform_api/live_http_listener.py +443 -0
  313. rbek/platform_api/public_execution_application.py +120 -0
  314. rbek/platform_api/public_rest_runtime.py +151 -0
  315. rbek/platform_api/rest_contract.py +396 -0
  316. rbek/platform_api/rest_server_adapter.py +321 -0
  317. rbek/platform_api/rest_transport.py +346 -0
  318. rbek/product_providers/__init__.py +0 -0
  319. rbek/product_providers/revpi/__init__.py +0 -0
  320. rbek/product_providers/revpi/certification.py +92 -0
  321. rbek/product_providers/revpi/evidence.py +100 -0
  322. rbek/product_providers/revpi/factory.py +70 -0
  323. rbek/product_providers/revpi/identity.py +70 -0
  324. rbek/product_providers/revpi/policy.py +110 -0
  325. rbek/product_providers/revpi/registry.py +115 -0
  326. rbek/product_providers/revpi/runtime_bridge.py +75 -0
  327. rbek/product_providers/revpi/runtime_context.py +68 -0
  328. rbek/protocols/__init__.py +0 -0
  329. rbek/providers/__init__.py +0 -0
  330. rbek/providers/adapter_capability_gate.py +31 -0
  331. rbek/providers/adapter_integration.py +170 -0
  332. rbek/providers/adapter_integration_gate.py +38 -0
  333. rbek/providers/adapter_registry.py +49 -0
  334. rbek/providers/adapters/__init__.py +71 -0
  335. rbek/providers/adapters/controlled_adapter_binding.py +111 -0
  336. rbek/providers/adapters/controlled_adapter_binding_base.py +256 -0
  337. rbek/providers/adapters/controlled_adapter_registry.py +96 -0
  338. rbek/providers/adapters/controlled_adapter_registry_base.py +143 -0
  339. rbek/providers/adapters/controlled_adapter_selection.py +107 -0
  340. rbek/providers/adapters/controlled_adapter_selection_base.py +170 -0
  341. rbek/providers/adapters/controlled_provider_adapter.py +127 -0
  342. rbek/providers/adapters/controlled_provider_adapter_base.py +117 -0
  343. rbek/providers/base/__init__.py +9 -0
  344. rbek/providers/base/controlled_execution_provider_base.py +126 -0
  345. rbek/providers/boot/__init__.py +0 -0
  346. rbek/providers/boot/neutral_provider_boot_lifecycle_gate.py +34 -0
  347. rbek/providers/boot/neutral_provider_boot_orchestration.py +83 -0
  348. rbek/providers/certification.py +96 -0
  349. rbek/providers/contracts/__init__.py +31 -0
  350. rbek/providers/contracts/controlled_execution_provider.py +177 -0
  351. rbek/providers/dependency/__init__.py +11 -0
  352. rbek/providers/dependency/neutral_provider_dependency_graph.py +31 -0
  353. rbek/providers/dependency/neutral_provider_dependency_lifecycle_gate.py +39 -0
  354. rbek/providers/dependency/neutral_provider_dependency_plan.py +30 -0
  355. rbek/providers/dependency/neutral_provider_dependency_runtime.py +178 -0
  356. rbek/providers/dependency/provider_dependency_runtime_orchestrator.py +159 -0
  357. rbek/providers/evidence.py +98 -0
  358. rbek/providers/governed_action/__init__.py +50 -0
  359. rbek/providers/governed_action/context.py +123 -0
  360. rbek/providers/governed_action/contracts.py +390 -0
  361. rbek/providers/governed_action/delegation.py +170 -0
  362. rbek/providers/governed_action/private_resolution.py +55 -0
  363. rbek/providers/graph/__init__.py +1 -0
  364. rbek/providers/graph/email_provider_factory.py +23 -0
  365. rbek/providers/identity.py +108 -0
  366. rbek/providers/invocation/__init__.py +27 -0
  367. rbek/providers/invocation/controlled_execution_provider_invocation.py +126 -0
  368. rbek/providers/invocation/controlled_execution_provider_invocation_base.py +197 -0
  369. rbek/providers/lifecycle/__init__.py +0 -0
  370. rbek/providers/lifecycle/neutral_provider_lifecycle.py +100 -0
  371. rbek/providers/lifecycle/neutral_provider_lifecycle_adapter_gate.py +34 -0
  372. rbek/providers/lifecycle/neutral_provider_lifecycle_registry_gate.py +39 -0
  373. rbek/providers/microsoft_graph/activation_evidence_redactor.py +53 -0
  374. rbek/providers/microsoft_graph/controlled_real_provider_activation_binding.py +92 -0
  375. rbek/providers/microsoft_graph/credential_reference_binding.py +46 -0
  376. rbek/providers/microsoft_graph/graph_endpoint_binding.py +51 -0
  377. rbek/providers/microsoft_graph/graph_network_authorization_policy.py +50 -0
  378. rbek/providers/microsoft_graph/mounted_file_secret_backend.py +77 -0
  379. rbek/providers/microsoft_graph/provider_activation_control.py +58 -0
  380. rbek/providers/policy.py +109 -0
  381. rbek/providers/registry/__init__.py +23 -0
  382. rbek/providers/registry/controlled_execution_provider_registry.py +104 -0
  383. rbek/providers/registry/controlled_execution_provider_registry_base.py +127 -0
  384. rbek/providers/registry.py +111 -0
  385. rbek/providers/runtime_composition.py +233 -0
  386. rbek/providers/runtime_composition_evidence.py +273 -0
  387. rbek/providers/runtime_composition_fingerprint.py +243 -0
  388. rbek/providers/runtime_composition_plan.py +267 -0
  389. rbek/providers/runtime_composition_validator.py +334 -0
  390. rbek/providers/runtime_context.py +120 -0
  391. rbek/providers/selection/__init__.py +25 -0
  392. rbek/providers/selection/controlled_execution_provider_selection.py +106 -0
  393. rbek/providers/selection/controlled_execution_provider_selection_base.py +152 -0
  394. rbek/registry/__init__.py +0 -0
  395. rbek/runtime/__init__.py +9 -0
  396. rbek/runtime/authorization_lease.py +853 -0
  397. rbek/runtime/bootstrap.py +160 -0
  398. rbek/runtime/capability_graph.py +262 -0
  399. rbek/runtime/controlled_effect_invocation.py +448 -0
  400. rbek/runtime/controlled_effect_runtime_integration.py +97 -0
  401. rbek/runtime/controlled_email_provider_activation_composition.py +253 -0
  402. rbek/runtime/controlled_email_provider_initializer.py +157 -0
  403. rbek/runtime/controlled_execution_dispatcher.py +112 -0
  404. rbek/runtime/controlled_execution_policy_gate.py +158 -0
  405. rbek/runtime/controlled_shell_design_gate.py +135 -0
  406. rbek/runtime/credential_evidence_projection.py +51 -0
  407. rbek/runtime/credential_reference_resolver.py +19 -0
  408. rbek/runtime/discovery.py +146 -0
  409. rbek/runtime/durable_governed_runtime_composition.py +2041 -0
  410. rbek/runtime/effect_attempt.py +268 -0
  411. rbek/runtime/effect_execution_provenance.py +546 -0
  412. rbek/runtime/effect_provenance_integration.py +153 -0
  413. rbek/runtime/email_ingestion_runtime.py +360 -0
  414. rbek/runtime/email_provider_configuration.py +237 -0
  415. rbek/runtime/enums.py +14 -0
  416. rbek/runtime/ephemeral_credential_material.py +77 -0
  417. rbek/runtime/events.py +162 -0
  418. rbek/runtime/exceptions.py +19 -0
  419. rbek/runtime/execution_adapter.py +93 -0
  420. rbek/runtime/execution_adapter_registry.py +112 -0
  421. rbek/runtime/execution_adapter_resolver.py +106 -0
  422. rbek/runtime/execution_adapter_validation.py +179 -0
  423. rbek/runtime/execution_audit_envelope.py +99 -0
  424. rbek/runtime/execution_effect.py +492 -0
  425. rbek/runtime/execution_pipeline.py +205 -0
  426. rbek/runtime/execution_store.py +569 -0
  427. rbek/runtime/external_execution_admission.py +354 -0
  428. rbek/runtime/governed_execution_authority.py +214 -0
  429. rbek/runtime/lifecycle.py +110 -0
  430. rbek/runtime/local_execution_admission.py +225 -0
  431. rbek/runtime/local_execution_contract.py +72 -0
  432. rbek/runtime/material_boundary.py +371 -0
  433. rbek/runtime/models.py +49 -0
  434. rbek/runtime/network_authorization_gate.py +40 -0
  435. rbek/runtime/noop_execution_adapter.py +101 -0
  436. rbek/runtime/observability.py +126 -0
  437. rbek/runtime/orchestrator.py +265 -0
  438. rbek/runtime/production_local_runtime_binding.py +1077 -0
  439. rbek/runtime/promoted_controlled_effect.py +406 -0
  440. rbek/runtime/runtime_api.py +472 -0
  441. rbek/runtime/runtime_authority_providers.py +1266 -0
  442. rbek/runtime/secret_reference_store.py +19 -0
  443. rbek/runtime/service_models.py +232 -0
  444. rbek/runtime/shell_audit_envelope.py +117 -0
  445. rbek/runtime/shell_command_validation.py +258 -0
  446. rbek/runtime/shell_dry_run_adapter.py +165 -0
  447. rbek/runtime/shell_execution_adapter.py +116 -0
  448. rbek/runtime/shell_execution_policy.py +173 -0
  449. rbek/runtime/source_cursor_checkpoint.py +408 -0
  450. rbek/runtime/sqlite_execution_store.py +1306 -0
  451. rbek/runtime/trusted_host_executable_origin_bridge.py +44 -0
  452. rbek/runtime/trusted_runtime_composition.py +615 -0
  453. rbek/runtime/validation.py +170 -0
  454. rbek/sdk/__init__.py +76 -0
  455. rbek/sdk/builder.py +57 -0
  456. rbek/sdk/client.py +56 -0
  457. rbek/sdk/context.py +38 -0
  458. rbek/sdk/exceptions.py +58 -0
  459. rbek/sdk/execution.py +115 -0
  460. rbek/sdk/runtime_bootstrap.py +963 -0
  461. rbek/sdk/runtime_execution.py +136 -0
  462. rbek/sdk/trusted_executable_process_declarations.py +284 -0
  463. rbek/sdk/trusted_live_executable_authority_origin.py +424 -0
  464. rbek/security/__init__.py +0 -0
  465. rbek/security/execution_safety_audit.py +130 -0
  466. rbek/security/execution_safety_decision.py +121 -0
  467. rbek/security/execution_safety_evaluation.py +134 -0
  468. rbek/security/execution_safety_policy.py +125 -0
  469. rbek/security/execution_safety_requirements.py +166 -0
  470. rbek/state/__init__.py +0 -0
  471. rbek/trust/__init__.py +0 -0
  472. rbek-0.2.1.dist-info/LICENSE +3 -0
  473. rbek-0.2.1.dist-info/METADATA +76 -0
  474. rbek-0.2.1.dist-info/RECORD +477 -0
  475. rbek-0.2.1.dist-info/WHEEL +5 -0
  476. rbek-0.2.1.dist-info/entry_points.txt +2 -0
  477. rbek-0.2.1.dist-info/top_level.txt +1 -0
rbek/__init__.py ADDED
File without changes
@@ -0,0 +1,17 @@
1
+ """Privacy-preserving adoption measurement primitives.
2
+
3
+ This package contains no HTTP listener, route registration, service startup,
4
+ or public activation authority.
5
+ """
6
+
7
+ from rbek.adoption.intake import (
8
+ AdoptionIntake,
9
+ AppendOnlyJsonlAdoptionStore,
10
+ IntakeResult,
11
+ )
12
+
13
+ __all__ = [
14
+ "AdoptionIntake",
15
+ "AppendOnlyJsonlAdoptionStore",
16
+ "IntakeResult",
17
+ ]
@@ -0,0 +1,89 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ import json
5
+ from typing import Final
6
+
7
+ from rbek.adoption.intake import AdoptionIntake, MAX_PAYLOAD_BYTES
8
+
9
+ JSON_CONTENT_TYPE: Final[str] = "application/json"
10
+
11
+
12
+ @dataclass(frozen=True, slots=True)
13
+ class AdoptionHttpResponse:
14
+ status_code: int
15
+ body: bytes
16
+ content_type: str = JSON_CONTENT_TYPE
17
+
18
+ def __post_init__(self) -> None:
19
+ if type(self.status_code) is not int:
20
+ raise TypeError("status_code must be int")
21
+ if type(self.body) is not bytes:
22
+ raise TypeError("body must be bytes")
23
+ if type(self.content_type) is not str:
24
+ raise TypeError("content_type must be str")
25
+
26
+
27
+ def _response(status_code: int, code: str) -> AdoptionHttpResponse:
28
+ return AdoptionHttpResponse(
29
+ status_code=status_code,
30
+ body=json.dumps(
31
+ {"status": code},
32
+ sort_keys=True,
33
+ separators=(",", ":"),
34
+ ).encode("utf-8"),
35
+ )
36
+
37
+
38
+ class AdoptionIntakeHttpAdapter:
39
+ __slots__ = ("_intake",)
40
+
41
+ def __init__(self, intake: AdoptionIntake) -> None:
42
+ if not isinstance(intake, AdoptionIntake):
43
+ raise TypeError("intake must be AdoptionIntake")
44
+ self._intake = intake
45
+
46
+ def handle(
47
+ self,
48
+ *,
49
+ method: str,
50
+ content_type: str | None,
51
+ body: bytes,
52
+ ) -> AdoptionHttpResponse:
53
+ if type(method) is not str:
54
+ return _response(400, "invalid_request")
55
+
56
+ if method.upper() != "POST":
57
+ return _response(405, "method_not_allowed")
58
+
59
+ if type(content_type) is not str:
60
+ return _response(415, "unsupported_media_type")
61
+
62
+ media_type = content_type.split(";", 1)[0].strip().lower()
63
+
64
+ if media_type != JSON_CONTENT_TYPE:
65
+ return _response(415, "unsupported_media_type")
66
+
67
+ if type(body) is not bytes:
68
+ return _response(400, "invalid_body")
69
+
70
+ if len(body) > MAX_PAYLOAD_BYTES:
71
+ return _response(413, "payload_too_large")
72
+
73
+ try:
74
+ decoded = body.decode("utf-8")
75
+ json.loads(decoded)
76
+ except (UnicodeDecodeError, json.JSONDecodeError):
77
+ return _response(422, "unprocessable_event")
78
+
79
+ try:
80
+ result = self._intake.receive(body)
81
+ except (TypeError, ValueError, UnicodeError, json.JSONDecodeError):
82
+ return _response(422, "unprocessable_event")
83
+ except Exception:
84
+ return _response(500, "internal_error")
85
+
86
+ return _response(
87
+ result.status_code,
88
+ result.reason,
89
+ )
@@ -0,0 +1,147 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
5
+ from io import BytesIO
6
+ from typing import Callable, Final, TypeAlias
7
+
8
+ from rbek.adoption.http_adapter import (
9
+ AdoptionHttpResponse,
10
+ AdoptionIntakeHttpAdapter,
11
+ )
12
+
13
+ DEFAULT_HOST: Final[str] = "127.0.0.1"
14
+ DEFAULT_PORT: Final[int] = 8766
15
+ EVENT_PATH: Final[str] = "/api/v1/adoption/events"
16
+ MAX_REQUEST_BODY_BYTES: Final[int] = 4096
17
+
18
+ ServerFactory: TypeAlias = Callable[
19
+ [tuple[str, int], type[BaseHTTPRequestHandler]],
20
+ ThreadingHTTPServer,
21
+ ]
22
+
23
+
24
+ def _write_response(
25
+ handler: BaseHTTPRequestHandler,
26
+ response: AdoptionHttpResponse,
27
+ ) -> None:
28
+ handler.send_response(response.status_code)
29
+ handler.send_header("Content-Type", response.content_type)
30
+ handler.send_header("Content-Length", str(len(response.body)))
31
+ handler.send_header("Cache-Control", "no-store")
32
+ handler.end_headers()
33
+ handler.wfile.write(response.body)
34
+
35
+
36
+ def build_request_handler(
37
+ adapter: AdoptionIntakeHttpAdapter,
38
+ ) -> type[BaseHTTPRequestHandler]:
39
+ class AdoptionRequestHandler(BaseHTTPRequestHandler):
40
+ server_version = "RBEKAdoption/1"
41
+ sys_version = ""
42
+
43
+ def log_message(self, format: str, *args: object) -> None:
44
+ return None
45
+
46
+ def _dispatch(self) -> None:
47
+ if self.path != EVENT_PATH:
48
+ response = AdoptionHttpResponse(
49
+ status_code=404,
50
+ body=b'{"status":"not_found"}',
51
+ )
52
+ _write_response(self, response)
53
+ return
54
+
55
+ content_length_raw = self.headers.get("Content-Length")
56
+
57
+ if content_length_raw is None:
58
+ response = AdoptionHttpResponse(
59
+ status_code=411,
60
+ body=b'{"status":"length_required"}',
61
+ )
62
+ _write_response(self, response)
63
+ return
64
+
65
+ try:
66
+ content_length = int(content_length_raw)
67
+ except ValueError:
68
+ response = AdoptionHttpResponse(
69
+ status_code=400,
70
+ body=b'{"status":"invalid_content_length"}',
71
+ )
72
+ _write_response(self, response)
73
+ return
74
+
75
+ if content_length < 0:
76
+ response = AdoptionHttpResponse(
77
+ status_code=400,
78
+ body=b'{"status":"invalid_content_length"}',
79
+ )
80
+ _write_response(self, response)
81
+ return
82
+
83
+ if content_length > MAX_REQUEST_BODY_BYTES:
84
+ response = AdoptionHttpResponse(
85
+ status_code=413,
86
+ body=b'{"status":"payload_too_large"}',
87
+ )
88
+ _write_response(self, response)
89
+ return
90
+
91
+ body = self.rfile.read(content_length)
92
+
93
+ response = adapter.handle(
94
+ method=self.command,
95
+ content_type=self.headers.get("Content-Type"),
96
+ body=body,
97
+ )
98
+
99
+ _write_response(self, response)
100
+
101
+ def do_POST(self) -> None:
102
+ self._dispatch()
103
+
104
+ def do_GET(self) -> None:
105
+ response = AdoptionHttpResponse(
106
+ status_code=405,
107
+ body=b'{"status":"method_not_allowed"}',
108
+ )
109
+ _write_response(self, response)
110
+
111
+ def do_PUT(self) -> None:
112
+ self.do_GET()
113
+
114
+ def do_DELETE(self) -> None:
115
+ self.do_GET()
116
+
117
+ def do_PATCH(self) -> None:
118
+ self.do_GET()
119
+
120
+ return AdoptionRequestHandler
121
+
122
+
123
+ @dataclass(frozen=True, slots=True)
124
+ class LocalAdoptionHttpListener:
125
+ adapter: AdoptionIntakeHttpAdapter
126
+ host: str = DEFAULT_HOST
127
+ port: int = DEFAULT_PORT
128
+ server_factory: ServerFactory = ThreadingHTTPServer
129
+
130
+ def __post_init__(self) -> None:
131
+ if not isinstance(self.adapter, AdoptionIntakeHttpAdapter):
132
+ raise TypeError("adapter must be AdoptionIntakeHttpAdapter")
133
+
134
+ if self.host != DEFAULT_HOST:
135
+ raise ValueError("local adoption listener must bind to 127.0.0.1")
136
+
137
+ if type(self.port) is not int or not (1 <= self.port <= 65535):
138
+ raise ValueError("port must be an integer in range 1..65535")
139
+
140
+ def serve_forever(self) -> None:
141
+ handler = build_request_handler(self.adapter)
142
+
143
+ with self.server_factory(
144
+ (self.host, self.port),
145
+ handler,
146
+ ) as server:
147
+ server.serve_forever()
@@ -0,0 +1,141 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from datetime import datetime, timezone
5
+ import json
6
+ from pathlib import Path
7
+ from typing import Mapping, Protocol
8
+
9
+ from rbek.cli.adoption_remote_contract import (
10
+ AdoptionEventValidationError,
11
+ validate_event_mapping,
12
+ )
13
+
14
+ MAX_PAYLOAD_BYTES = 4096
15
+
16
+
17
+ class AdoptionStore(Protocol):
18
+ def append(
19
+ self,
20
+ event: Mapping[str, str],
21
+ *,
22
+ received_at_server: str,
23
+ ) -> None:
24
+ """Persist one already validated non-identifying event."""
25
+
26
+
27
+ @dataclass(frozen=True, slots=True)
28
+ class IntakeResult:
29
+ accepted: bool
30
+ status_code: int
31
+ reason: str
32
+
33
+
34
+ @dataclass(frozen=True, slots=True)
35
+ class AppendOnlyJsonlAdoptionStore:
36
+ path: Path
37
+
38
+ def append(
39
+ self,
40
+ event: Mapping[str, str],
41
+ *,
42
+ received_at_server: str,
43
+ ) -> None:
44
+ self.path.parent.mkdir(
45
+ parents=True,
46
+ exist_ok=True,
47
+ )
48
+
49
+ row = dict(event)
50
+ row["received_at_server"] = received_at_server
51
+
52
+ encoded = (
53
+ json.dumps(
54
+ row,
55
+ sort_keys=True,
56
+ separators=(",", ":"),
57
+ )
58
+ + "\n"
59
+ ).encode("utf-8")
60
+
61
+ with self.path.open("ab") as handle:
62
+ handle.write(encoded)
63
+ handle.flush()
64
+
65
+
66
+ @dataclass(frozen=True, slots=True)
67
+ class AdoptionIntake:
68
+ store: AdoptionStore
69
+
70
+ def receive(
71
+ self,
72
+ body: bytes,
73
+ *,
74
+ received_at_server: str | None = None,
75
+ ) -> IntakeResult:
76
+ if type(body) is not bytes:
77
+ return IntakeResult(
78
+ accepted=False,
79
+ status_code=400,
80
+ reason="body_must_be_bytes",
81
+ )
82
+
83
+ if len(body) == 0:
84
+ return IntakeResult(
85
+ accepted=False,
86
+ status_code=400,
87
+ reason="empty_payload",
88
+ )
89
+
90
+ if len(body) > MAX_PAYLOAD_BYTES:
91
+ return IntakeResult(
92
+ accepted=False,
93
+ status_code=413,
94
+ reason="payload_too_large",
95
+ )
96
+
97
+ try:
98
+ decoded = json.loads(body.decode("utf-8"))
99
+ except (UnicodeDecodeError, json.JSONDecodeError):
100
+ return IntakeResult(
101
+ accepted=False,
102
+ status_code=400,
103
+ reason="invalid_json",
104
+ )
105
+
106
+ if not isinstance(decoded, dict):
107
+ return IntakeResult(
108
+ accepted=False,
109
+ status_code=422,
110
+ reason="payload_must_be_object",
111
+ )
112
+
113
+ try:
114
+ event = validate_event_mapping(decoded)
115
+ except AdoptionEventValidationError:
116
+ return IntakeResult(
117
+ accepted=False,
118
+ status_code=422,
119
+ reason="invalid_event_contract",
120
+ )
121
+
122
+ timestamp = received_at_server
123
+
124
+ if timestamp is None:
125
+ timestamp = (
126
+ datetime.now(timezone.utc)
127
+ .replace(microsecond=0)
128
+ .isoformat()
129
+ .replace("+00:00", "Z")
130
+ )
131
+
132
+ self.store.append(
133
+ event,
134
+ received_at_server=timestamp,
135
+ )
136
+
137
+ return IntakeResult(
138
+ accepted=True,
139
+ status_code=202,
140
+ reason="accepted",
141
+ )
@@ -0,0 +1,274 @@
1
+ from __future__ import annotations
2
+
3
+ from datetime import (
4
+ datetime,
5
+ timedelta,
6
+ timezone,
7
+ )
8
+ import fcntl
9
+ import json
10
+ import os
11
+ from pathlib import Path
12
+ from typing import Any
13
+
14
+ DEFAULT_STATE_ROOT = Path(
15
+ "/var/lib/rbek-adoption"
16
+ )
17
+
18
+ DEFAULT_EVENT_LOG = (
19
+ DEFAULT_STATE_ROOT
20
+ / "events.jsonl"
21
+ )
22
+
23
+ DEFAULT_RECEIPT_LOG = (
24
+ DEFAULT_STATE_ROOT
25
+ / "events.receipts.jsonl"
26
+ )
27
+
28
+ DEFAULT_LOCK_FILE = (
29
+ DEFAULT_STATE_ROOT
30
+ / "events.write.lock"
31
+ )
32
+
33
+ RETENTION_DAYS = 30
34
+
35
+
36
+ def _parse_server_time(
37
+ value: str,
38
+ ) -> datetime:
39
+ parsed = datetime.fromisoformat(
40
+ value.replace(
41
+ "Z",
42
+ "+00:00",
43
+ )
44
+ )
45
+
46
+ if parsed.tzinfo is None:
47
+ raise ValueError(
48
+ "received_at_server must be timezone-aware"
49
+ )
50
+
51
+ return parsed.astimezone(
52
+ timezone.utc
53
+ )
54
+
55
+
56
+ def _rewrite(
57
+ path: Path,
58
+ lines: list[str],
59
+ ) -> None:
60
+ temporary = path.with_name(
61
+ path.name
62
+ + ".retention.tmp"
63
+ )
64
+
65
+ payload = "".join(
66
+ line + "\n"
67
+ for line in lines
68
+ ).encode(
69
+ "utf-8"
70
+ )
71
+
72
+ fd = os.open(
73
+ temporary,
74
+ os.O_WRONLY
75
+ | os.O_CREAT
76
+ | os.O_TRUNC,
77
+ 0o640,
78
+ )
79
+
80
+ try:
81
+ written = 0
82
+
83
+ while written < len(payload):
84
+ count = os.write(
85
+ fd,
86
+ payload[written:],
87
+ )
88
+
89
+ if count <= 0:
90
+ raise OSError(
91
+ "retention rewrite failed"
92
+ )
93
+
94
+ written += count
95
+
96
+ os.fsync(fd)
97
+
98
+ finally:
99
+ os.close(fd)
100
+
101
+ os.replace(
102
+ temporary,
103
+ path,
104
+ )
105
+
106
+
107
+ def prune_expired_events(
108
+ *,
109
+ event_log: Path = DEFAULT_EVENT_LOG,
110
+ receipt_log: Path = DEFAULT_RECEIPT_LOG,
111
+ lock_file: Path = DEFAULT_LOCK_FILE,
112
+ now: datetime | None = None,
113
+ retention_days: int = RETENTION_DAYS,
114
+ ) -> dict[str, int]:
115
+
116
+ if retention_days != 30:
117
+ raise ValueError(
118
+ "retention_days must be exactly 30"
119
+ )
120
+
121
+ current = (
122
+ now
123
+ or datetime.now(
124
+ timezone.utc
125
+ )
126
+ )
127
+
128
+ if current.tzinfo is None:
129
+ raise ValueError(
130
+ "now must be timezone-aware"
131
+ )
132
+
133
+ cutoff = (
134
+ current.astimezone(
135
+ timezone.utc
136
+ )
137
+ - timedelta(
138
+ days=30
139
+ )
140
+ )
141
+
142
+ event_log = Path(
143
+ event_log
144
+ )
145
+
146
+ receipt_log = Path(
147
+ receipt_log
148
+ )
149
+
150
+ lock_file = Path(
151
+ lock_file
152
+ )
153
+
154
+ lock_file.parent.mkdir(
155
+ mode=0o750,
156
+ parents=True,
157
+ exist_ok=True,
158
+ )
159
+
160
+ lock_fd = os.open(
161
+ lock_file,
162
+ os.O_WRONLY
163
+ | os.O_CREAT,
164
+ 0o640,
165
+ )
166
+
167
+ try:
168
+ fcntl.flock(
169
+ lock_fd,
170
+ fcntl.LOCK_EX,
171
+ )
172
+
173
+ events = (
174
+ event_log.read_text(
175
+ encoding="utf-8"
176
+ ).splitlines()
177
+ if event_log.exists()
178
+ else []
179
+ )
180
+
181
+ receipts = (
182
+ receipt_log.read_text(
183
+ encoding="utf-8"
184
+ ).splitlines()
185
+ if receipt_log.exists()
186
+ else []
187
+ )
188
+
189
+ if len(events) != len(receipts):
190
+ raise RuntimeError(
191
+ "event/receipt "
192
+ "line-count mismatch: "
193
+ f"{len(events)} != "
194
+ f"{len(receipts)}"
195
+ )
196
+
197
+ kept_events: list[str] = []
198
+ kept_receipts: list[str] = []
199
+
200
+ removed = 0
201
+
202
+ for event_line, receipt_line in zip(
203
+ events,
204
+ receipts,
205
+ ):
206
+ receipt: Any = json.loads(
207
+ receipt_line
208
+ )
209
+
210
+ received_value = receipt.get(
211
+ "received_at_server"
212
+ )
213
+
214
+ if not isinstance(
215
+ received_value,
216
+ str,
217
+ ):
218
+ raise RuntimeError(
219
+ "receipt metadata missing "
220
+ "received_at_server"
221
+ )
222
+
223
+ received = _parse_server_time(
224
+ received_value
225
+ )
226
+
227
+ if received < cutoff:
228
+ removed += 1
229
+ continue
230
+
231
+ kept_events.append(
232
+ event_line
233
+ )
234
+
235
+ kept_receipts.append(
236
+ receipt_line
237
+ )
238
+
239
+ if removed:
240
+ _rewrite(
241
+ event_log,
242
+ kept_events,
243
+ )
244
+
245
+ _rewrite(
246
+ receipt_log,
247
+ kept_receipts,
248
+ )
249
+
250
+ return {
251
+ "before":
252
+ len(events),
253
+
254
+ "removed":
255
+ removed,
256
+
257
+ "after":
258
+ len(kept_events),
259
+ }
260
+
261
+ finally:
262
+ try:
263
+ fcntl.flock(
264
+ lock_fd,
265
+ fcntl.LOCK_UN,
266
+ )
267
+ finally:
268
+ os.close(
269
+ lock_fd
270
+ )
271
+
272
+
273
+ def prune_default_retention() -> dict[str, int]:
274
+ return prune_expired_events()