hypernix 0.72.2.post3__tar.gz → 0.72.2.post5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (433) hide show
  1. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/PKG-INFO +1 -1
  2. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/pyproject.toml +1 -1
  3. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/setup.cfg +1 -1
  4. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/__init__.py +1 -1
  5. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/hyperlink/__init__.py +3 -1
  6. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/security/keymaster.py +163 -0
  7. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/auth.py +56 -1
  8. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/deps.py +40 -1
  9. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/auth.py +69 -1
  10. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/authundo.py +25 -0
  11. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/version.py +8 -3
  12. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1sdk/__init__.py +9 -4
  13. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/waiter/__init__.py +7 -1
  14. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/waiter/discovery.py +8 -2
  15. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix.egg-info/SOURCES.txt +2 -0
  16. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_lint_regressions.py +43 -0
  17. hypernix-0.72.2.post5/tests/test_t1_v1_0_26_8_1_1.py +390 -0
  18. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1_v1_0_26_core.py +33 -19
  19. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1_v1_0_26_http.py +2 -2
  20. hypernix-0.72.2.post5/tests/test_t2s_errors.py +325 -0
  21. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0721_api_waiter.py +14 -3
  22. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Changelog.md +115 -0
  23. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Release-Timeline.md +11 -0
  24. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/T1-API.md +63 -0
  25. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/.github/workflows/build.yml +0 -0
  26. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/.github/workflows/ci.yml +0 -0
  27. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/.github/workflows/deploy-docs.yml +0 -0
  28. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/.github/workflows/ios.yml +0 -0
  29. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/.github/workflows/public-release.yml +0 -0
  30. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/.github/workflows/release.yml +0 -0
  31. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/.github/workflows/update-json-stats.yml +0 -0
  32. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/LICENSE +0 -0
  33. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/MANIFEST.in +0 -0
  34. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/README.md +0 -0
  35. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/assets/logo/Gemini_Generated_Image_nxfdm1nxfdm1nxfd-removebg-preview.png +0 -0
  36. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/assets/logo/Gemini_Generated_Image_nxfdm1nxfdm1nxfd.png +0 -0
  37. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/assets/logo.png +0 -0
  38. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/assets/logo1.png +0 -0
  39. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/curriculum_eval_v0_70_4.py +0 -0
  40. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/custom_arch.py +0 -0
  41. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/hypernix_run.json +0 -0
  42. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/quickstart.py +0 -0
  43. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/resilient_finetune_v0_70_4.py +0 -0
  44. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/run_hypernix.py +0 -0
  45. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/.env.example +0 -0
  46. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/API-EXAMPLES.md +0 -0
  47. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/Dockerfile +0 -0
  48. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/README.md +0 -0
  49. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/config/.gitkeep +0 -0
  50. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/docker-compose.yml +0 -0
  51. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/hypernix-t1api.service +0 -0
  52. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/nginx.conf +0 -0
  53. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/openapi.json +0 -0
  54. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/run_local.sh +0 -0
  55. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/run_tailscale.sh +0 -0
  56. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/train hypernix 1 5 gtx1080.py +0 -0
  57. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/train_hypernix_0_1_5_evaluator.py +0 -0
  58. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/train_hypernix_1_5_gtx1080.py +0 -0
  59. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/upload_to_hub.py +0 -0
  60. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/pytest.ini +0 -0
  61. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/ruff.toml +0 -0
  62. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/README.md +0 -0
  63. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/apply_hypernix_fixes.py +0 -0
  64. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/autofix +0 -0
  65. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/autofix-B +0 -0
  66. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/autofix-E +0 -0
  67. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/autofix-F +0 -0
  68. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/autofix_scope.py +0 -0
  69. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/benchmark_v5.py +0 -0
  70. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/benchmark_v5s.py +0 -0
  71. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/benchmark_v6.py +0 -0
  72. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/install_deps.sh +0 -0
  73. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/install_macos_legacy.sh +0 -0
  74. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/measure_optimizer_memory.py +0 -0
  75. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/quantize_i7_7660u.sh +0 -0
  76. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/t1api_examples.py +0 -0
  77. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/update_json_stats.py +0 -0
  78. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/setup.py +0 -0
  79. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/__main__.py +0 -0
  80. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/bridge/__init__.py +0 -0
  81. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/bridge/lmstudio.py +0 -0
  82. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/chat/__init__.py +0 -0
  83. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/chat/cookbook.py +0 -0
  84. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/chat/countertop.py +0 -0
  85. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/chat/flour.py +0 -0
  86. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/chat/injection.py +0 -0
  87. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/chat/menu.py +0 -0
  88. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/__init__.py +0 -0
  89. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/blender.py +0 -0
  90. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/cardboard_box.py +0 -0
  91. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/cutting_board.py +0 -0
  92. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/food_processor.py +0 -0
  93. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/lunchbox.py +0 -0
  94. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/mediocre_fridge.py +0 -0
  95. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/pans.py +0 -0
  96. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/pepper_shaker.py +0 -0
  97. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/qa.py +0 -0
  98. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/salt_shaker.py +0 -0
  99. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/scavenger.py +0 -0
  100. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/sink.py +0 -0
  101. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/strainer.py +0 -0
  102. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/toaster.py +0 -0
  103. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/tupperware.py +0 -0
  104. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/evaluation/__init__.py +0 -0
  105. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/evaluation/espresso_maker.py +0 -0
  106. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/evaluation/industrial_range.py +0 -0
  107. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/evaluation/new_fridge.py +0 -0
  108. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/evaluation/new_range.py +0 -0
  109. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/evaluation/old_range.py +0 -0
  110. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/evaluation/vera.py +0 -0
  111. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/hyped_pro.js +0 -0
  112. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/hyperlink/discovery.py +0 -0
  113. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/hyperlink/files.py +0 -0
  114. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/hyperlink/hfdownload.py +0 -0
  115. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/hyperlink/hfmerge.py +0 -0
  116. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/hyperlink/pairing.py +0 -0
  117. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/hyperlink/sessions.py +0 -0
  118. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/__init__.py +0 -0
  119. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/assistant.py +0 -0
  120. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/cli.py +0 -0
  121. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/hyped.py +0 -0
  122. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/hyped_pro.py +0 -0
  123. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/hyped_pro_bridge.py +0 -0
  124. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/hyped_pro_core.py +0 -0
  125. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/hyped_pro_gui.py +0 -0
  126. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/hyped_pro_tools.py +0 -0
  127. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/noodle/__init__.py +0 -0
  128. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/noodle/agent.py +0 -0
  129. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/noodle/cli.py +0 -0
  130. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/noodle/hpo.py +0 -0
  131. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/noodle/providers.py +0 -0
  132. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/noodle/swarm.py +0 -0
  133. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/noodle/tools.py +0 -0
  134. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/noodle/validate.py +0 -0
  135. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/version_launcher.py +0 -0
  136. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/websearch.py +0 -0
  137. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/wiki_cli.py +0 -0
  138. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/__init__.py +0 -0
  139. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/arch.py +0 -0
  140. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/download.py +0 -0
  141. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/generate.py +0 -0
  142. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/microwave.py +0 -0
  143. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/multilama.py +0 -0
  144. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/nano_nano.py +0 -0
  145. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/neo_oven.py +0 -0
  146. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/old_oven.py +0 -0
  147. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/stml.py +0 -0
  148. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/whisk.py +0 -0
  149. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/workshop.py +0 -0
  150. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/__init__.py +0 -0
  151. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/cctvtop.py +0 -0
  152. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/hyper_log.py +0 -0
  153. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/livestream.py +0 -0
  154. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/map.py +0 -0
  155. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/plasma.py +0 -0
  156. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/table.py +0 -0
  157. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/thermometer.py +0 -0
  158. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/tv.py +0 -0
  159. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/tvtop.py +0 -0
  160. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/tvtop_plus_plus.py +0 -0
  161. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/optimizers/__init__.py +0 -0
  162. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/optimizers/optimizer_framework.py +0 -0
  163. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/optimizers/pressure_cooker.py +0 -0
  164. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/optimizers/pressure_cooker_v3.py +0 -0
  165. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/optimizers/pressure_cooker_v4.py +0 -0
  166. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/optimizers/pressure_cooker_v5.py +0 -0
  167. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/optimizers/pressure_cooker_v5s.py +0 -0
  168. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/optimizers/pressure_cooker_v6.py +0 -0
  169. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/optimizers/pressure_cooker_v6v.py +0 -0
  170. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/optimizers/sixbit.py +0 -0
  171. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/package-lock.json +0 -0
  172. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/package.json +0 -0
  173. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/py.typed +0 -0
  174. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/quant/__init__.py +0 -0
  175. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/quant/convert.py +0 -0
  176. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/quant/fetcher.py +0 -0
  177. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/quant/formats.py +0 -0
  178. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/quant/quantize.py +0 -0
  179. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/quant/steamroller.py +0 -0
  180. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/quant/steamroller_cli.py +0 -0
  181. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/quant/upload.py +0 -0
  182. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/scriptgen/__init__.py +0 -0
  183. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/scriptgen/app.py +0 -0
  184. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/scriptgen/cli.py +0 -0
  185. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/scriptgen/params.py +0 -0
  186. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/scriptgen/templates.py +0 -0
  187. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/scriptgen/theme.py +0 -0
  188. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/scriptgen/widgets.py +0 -0
  189. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/security/__init__.py +0 -0
  190. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/security/gatekeeper.py +0 -0
  191. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/security/gkey_cli.py +0 -0
  192. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/security/keyversions.py +0 -0
  193. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/security/t2keys.py +0 -0
  194. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/__init__.py +0 -0
  195. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/compactor.py +0 -0
  196. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/config.py +0 -0
  197. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/deps.py +0 -0
  198. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/dishwasher.py +0 -0
  199. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/doctor.py +0 -0
  200. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/ethanol.py +0 -0
  201. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/freezer.py +0 -0
  202. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/net.py +0 -0
  203. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/old_fridge.py +0 -0
  204. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/outage.py +0 -0
  205. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/pascal.py +0 -0
  206. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/pathfix.py +0 -0
  207. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/protect.py +0 -0
  208. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/release.py +0 -0
  209. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/torch_compat.py +0 -0
  210. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/ups.py +0 -0
  211. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/utils.py +0 -0
  212. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/__init__.py +0 -0
  213. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/app.py +0 -0
  214. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/audit.py +0 -0
  215. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/authhistory.py +0 -0
  216. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/backup.py +0 -0
  217. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/billing.py +0 -0
  218. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/config.py +0 -0
  219. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/cost.py +0 -0
  220. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/data/model_registry.example.json +0 -0
  221. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/data/routing_policies.example.json +0 -0
  222. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/db.py +0 -0
  223. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/deploy.py +0 -0
  224. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/errors.py +0 -0
  225. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/events.py +0 -0
  226. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/jobs.py +0 -0
  227. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/keys.py +0 -0
  228. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/modules.py +0 -0
  229. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/mtls.py +0 -0
  230. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/netpolicy.py +0 -0
  231. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/ratelimit.py +0 -0
  232. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/registry.py +0 -0
  233. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/__init__.py +0 -0
  234. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/audit.py +0 -0
  235. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/backup.py +0 -0
  236. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/billing.py +0 -0
  237. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/bridge.py +0 -0
  238. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/config.py +0 -0
  239. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/events.py +0 -0
  240. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/health.py +0 -0
  241. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/hyperlink.py +0 -0
  242. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/jobs.py +0 -0
  243. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/keys.py +0 -0
  244. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/models.py +0 -0
  245. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/modules.py +0 -0
  246. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/security.py +0 -0
  247. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/servers.py +0 -0
  248. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/usage.py +0 -0
  249. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routing.py +0 -0
  250. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/schemas.py +0 -0
  251. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/security.py +0 -0
  252. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/servers.py +0 -0
  253. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/storage.py +0 -0
  254. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/transport.py +0 -0
  255. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/usage.py +0 -0
  256. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1sdk/client.py +0 -0
  257. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1sdk/errors.py +0 -0
  258. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1sdk/models.py +0 -0
  259. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1sdk/transport.py +0 -0
  260. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/timing/__init__.py +0 -0
  261. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/timing/bell.py +0 -0
  262. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/timing/coffee_maker.py +0 -0
  263. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/timing/smoke_alarm.py +0 -0
  264. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/timing/spinner.py +0 -0
  265. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/timing/timer.py +0 -0
  266. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/__init__.py +0 -0
  267. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/abbicus.py +0 -0
  268. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/apron.py +0 -0
  269. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/brewer.py +0 -0
  270. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/cake_pan.py +0 -0
  271. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/camouflage.py +0 -0
  272. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/compute_framework.py +0 -0
  273. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/deep_fryer.py +0 -0
  274. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/fizzle.py +0 -0
  275. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/instant_pot.py +0 -0
  276. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/lazy_suzan.py +0 -0
  277. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/mtp.py +0 -0
  278. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/recipe_book.py +0 -0
  279. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/smoker.py +0 -0
  280. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/train.py +0 -0
  281. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/tsconfig.json +0 -0
  282. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/waiter/cli.py +0 -0
  283. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/waiter/client.py +0 -0
  284. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/waiter/diagnose.py +0 -0
  285. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/waiter/local_config.py +0 -0
  286. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/waiter/smoke.py +0 -0
  287. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/waiter/tui.py +0 -0
  288. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_alarms_and_presets.py +0 -0
  289. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_arch_mapping.py +0 -0
  290. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_assistant.py +0 -0
  291. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_autofix_scripts.py +0 -0
  292. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_cli_integration.py +0 -0
  293. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_coverage_beef.py +0 -0
  294. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_deps_and_windows.py +0 -0
  295. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_ethanol.py +0 -0
  296. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_fetcher.py +0 -0
  297. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_freezer.py +0 -0
  298. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_fridges.py +0 -0
  299. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_gkey_key_versions.py +0 -0
  300. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_hyped_pro_bridge_cancel.py +0 -0
  301. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_hyped_pro_t1api.py +0 -0
  302. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_install_pin.py +0 -0
  303. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_install_script.py +0 -0
  304. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_kitchen_v044.py +0 -0
  305. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_kitchen_v045.py +0 -0
  306. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_lazy_suzan.py +0 -0
  307. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_lunchbox.py +0 -0
  308. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_map.py +0 -0
  309. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_module_layout.py +0 -0
  310. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_neo_oven.py +0 -0
  311. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_neo_oven_generation.py +0 -0
  312. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_new_archs_v035.py +0 -0
  313. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_nix_fallback.py +0 -0
  314. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_old_oven.py +0 -0
  315. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_pathfix.py +0 -0
  316. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_pressure_cooker_v048.py +0 -0
  317. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_pressure_cooker_v3.py +0 -0
  318. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_pressure_cooker_v6.py +0 -0
  319. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_quantize_v0703.py +0 -0
  320. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_ranges.py +0 -0
  321. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_shakers_and_torchcompat.py +0 -0
  322. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_snapshot_roundtrip.py +0 -0
  323. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_auth.py +0 -0
  324. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_beta3_core.py +0 -0
  325. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_beta3_http.py +0 -0
  326. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_beta3_security.py +0 -0
  327. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_beta4_usage_report.py +0 -0
  328. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_billing.py +0 -0
  329. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_core.py +0 -0
  330. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_events.py +0 -0
  331. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_example_scripts.py +0 -0
  332. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_http.py +0 -0
  333. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_http_beta2.py +0 -0
  334. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_jobs.py +0 -0
  335. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_modules.py +0 -0
  336. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_routing.py +0 -0
  337. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_security.py +0 -0
  338. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_servers.py +0 -0
  339. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_tupperware.py +0 -0
  340. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_tvtop_plus_plus_comprehensive.py +0 -0
  341. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_ups.py +0 -0
  342. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v031_chat_and_archs.py +0 -0
  343. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v047_deep_fryer_cake_pan_presets.py +0 -0
  344. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v050.py +0 -0
  345. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v051.py +0 -0
  346. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v051_1.py +0 -0
  347. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v051_3.py +0 -0
  348. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v051_4.py +0 -0
  349. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v052_5.py +0 -0
  350. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v052_6.py +0 -0
  351. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v060.py +0 -0
  352. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v061_1.py +0 -0
  353. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v061_2.py +0 -0
  354. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v061_b1.py +0 -0
  355. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0703_additional.py +0 -0
  356. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0704_features.py +0 -0
  357. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0704_tvtop_plus_plus.py +0 -0
  358. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0704b11_features.py +0 -0
  359. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0704b12_cctvtop.py +0 -0
  360. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0705_all.py +0 -0
  361. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0710_gatekeeper_keymaster.py +0 -0
  362. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0711_border_fix.py +0 -0
  363. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0712_hyped_countertop.py +0 -0
  364. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0714_config_provider_keys.py +0 -0
  365. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0714_cpu_presets.py +0 -0
  366. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0714_hyped_pro_bridge.py +0 -0
  367. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0714_hyped_pro_core.py +0 -0
  368. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0714_hyped_pro_launcher.py +0 -0
  369. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0714_hyped_pro_tools.py +0 -0
  370. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0714_multilama.py +0 -0
  371. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0721_modules.py +0 -0
  372. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0721_t2_keys.py +0 -0
  373. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_vera.py +0 -0
  374. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_version_launcher.py +0 -0
  375. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_waiter.py +0 -0
  376. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_waiter_diagnose.py +0 -0
  377. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Abbicus.md +0 -0
  378. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Alarms.md +0 -0
  379. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Apron.md +0 -0
  380. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Architectures.md +0 -0
  381. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Bell.md +0 -0
  382. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Blender.md +0 -0
  383. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/CLI.md +0 -0
  384. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/CakePan.md +0 -0
  385. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Camouflage.md +0 -0
  386. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/CoffeeMaker.md +0 -0
  387. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Convert.md +0 -0
  388. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Cookbook.md +0 -0
  389. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Countertop.md +0 -0
  390. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/CuttingBoard.md +0 -0
  391. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Dashboards.md +0 -0
  392. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/DeepFryer.md +0 -0
  393. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Download.md +0 -0
  394. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/EspressoMaker.md +0 -0
  395. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Flour.md +0 -0
  396. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/FoodProcessor.md +0 -0
  397. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Frameworks.md +0 -0
  398. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Freezer.md +0 -0
  399. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Fridges.md +0 -0
  400. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Home.md +0 -0
  401. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/HuggingFace-Models.md +0 -0
  402. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/HyperLog.md +0 -0
  403. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Kitchen.md +0 -0
  404. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Lunchbox.md +0 -0
  405. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/MTP.md +0 -0
  406. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Menu.md +0 -0
  407. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Microwave.md +0 -0
  408. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Optimizers.md +0 -0
  409. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Ovens.md +0 -0
  410. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Pans.md +0 -0
  411. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Pascal.md +0 -0
  412. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/PipelineMechanics.md +0 -0
  413. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Pressure-Cooker-V3.md +0 -0
  414. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Pressure-Cooker-V4.md +0 -0
  415. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Pressure-Cooker-V5.md +0 -0
  416. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Pressure-Cooker-V6.md +0 -0
  417. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Quantization.md +0 -0
  418. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Ranges.md +0 -0
  419. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/RecipeBook.md +0 -0
  420. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Roadmap.md +0 -0
  421. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/STML.md +0 -0
  422. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Scavenger.md +0 -0
  423. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Shakers.md +0 -0
  424. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Smoker.md +0 -0
  425. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/T1-API-Security-Checklist.md +0 -0
  426. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Toaster.md +0 -0
  427. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Training.md +0 -0
  428. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Tupperware.md +0 -0
  429. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Vera.md +0 -0
  430. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Waiter-TUI.md +0 -0
  431. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Whisk.md +0 -0
  432. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Workshop.md +0 -0
  433. {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/macOS-legacy.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hypernix
3
- Version: 0.72.2.post3
3
+ Version: 0.72.2.post5
4
4
  Summary: Download and quantize the HyperNix PyTorch model to GGUF (fp32/fp16/Q8_0/Q6_K/Q4_K_M).
5
5
  Home-page: https://github.com/minerofthesoal/hypernix-pip
6
6
  Author: HyperNix contributors
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "hypernix"
7
- version = "0.72.2.post3"
7
+ version = "0.72.2.post5"
8
8
  description = "Download and quantize the HyperNix PyTorch model to GGUF (fp32/fp16/Q8_0/Q6_K/Q4_K_M)."
9
9
  readme = { file = "README.md", content-type = "text/markdown" }
10
10
  license = { text = "HOL-1.0" }
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = hypernix
3
- version = 0.72.2.post3
3
+ version = 0.72.2.post5
4
4
  description = Download and quantize the HyperNix PyTorch model to GGUF (fp32/fp16/Q8_0/Q6_K/Q4_K_M).
5
5
  long_description = file: README.md
6
6
  long_description_content_type = text/markdown
@@ -63,7 +63,7 @@ import importlib.util
63
63
  import sys
64
64
  from typing import TYPE_CHECKING, Any
65
65
 
66
- __version__ = "0.72.2-3"
66
+ __version__ = "0.72.2.post5"
67
67
  DEFAULT_REPO_ID = "ray0rf1re/hyper-Nix.2"
68
68
  DEFAULT_MODEL = "qwen3.5-4b" # New default model
69
69
 
@@ -27,13 +27,15 @@ everything here is testable with no web layer in the way.
27
27
  """
28
28
  from __future__ import annotations
29
29
 
30
+ # Derived rather than repeated — see hypernix.waiter.__init__ for why.
31
+ from ..t1api.version import T1_VERSION_SHORT as _T1_VERSION_SHORT
30
32
  from .discovery import Endpoint, advertise, local_endpoints
31
33
  from .files import Attachment, AttachmentStore
32
34
  from .hfmerge import HFRef, HFResolveError, ResolvedModel, merge, parse_link, resolve
33
35
  from .pairing import DeviceRecord, DeviceRegistry, PairingCode, pairing_payload
34
36
  from .sessions import ChatMessage, ChatSession, ChatSessionStore
35
37
 
36
- __hyperlink_version__ = "1.0.26.8.1.0"
38
+ __hyperlink_version__ = _T1_VERSION_SHORT
37
39
 
38
40
  __all__ = [
39
41
  "__hyperlink_version__",
@@ -68,6 +68,7 @@ import threading
68
68
  import time
69
69
  import uuid
70
70
  import warnings
71
+ from collections.abc import Iterable
71
72
  from dataclasses import dataclass
72
73
  from datetime import UTC, datetime
73
74
  from enum import StrEnum
@@ -157,6 +158,18 @@ def _format_server_id(seq: int, letter: str, gen: int) -> str:
157
158
  return f"{seq:05d}-{letter}{gen}"
158
159
 
159
160
 
161
+ def _server_id_order(server_id: str) -> tuple[int, int, int]:
162
+ """Sort key for a server ID, in the order it actually advances.
163
+
164
+ ``_next_server_id`` bumps the sequence, rolls it into the letter, and
165
+ rolls the letter into the generation — so generation is the most
166
+ significant part and sequence the least. Sorting the raw strings would
167
+ put ``00002-A1`` after ``00001-B1``, which is backwards.
168
+ """
169
+ seq, letter, gen = _parse_server_id(server_id)
170
+ return (gen, ord(letter), seq)
171
+
172
+
160
173
  def _next_server_id(current: str) -> str:
161
174
  """Increment a server ID, cycling through A–Z then bumping the generation."""
162
175
  seq, letter, gen = _parse_server_id(current)
@@ -430,6 +443,7 @@ class Keymaster:
430
443
  )
431
444
 
432
445
  self._load_all()
446
+ self._resume_server_id(server_id)
433
447
 
434
448
  self._stop_event = threading.Event()
435
449
  self._bg_thread: threading.Thread | None = None
@@ -494,6 +508,60 @@ class Keymaster:
494
508
  if meta:
495
509
  self._keys[meta.key_id] = meta
496
510
 
511
+ def _resume_server_id(self, requested_start: str) -> None:
512
+ """Continue the server-ID sequence from what the store already holds.
513
+
514
+ The counter only ever lived in memory, so every process started
515
+ again at ``00001-A1`` — and since each ``gkey`` invocation is its
516
+ own process, every key ever minted from the CLI carried the same
517
+ server ID. The field was there, documented, and constant.
518
+
519
+ Archived keys are scanned too. ``_load_all`` reads only the active
520
+ store, and revoking a key moves it into ``archive/``; resuming
521
+ from the active keys alone would hand a revoked key's server ID to
522
+ a new key the moment the highest-numbered one was revoked. A
523
+ server ID that comes back around is worse than one that never
524
+ moves, because audit trails stop being able to tell the two keys
525
+ apart.
526
+
527
+ An explicitly requested start still wins when it is ahead of the
528
+ store, so a caller can move a fresh sequence forward on purpose.
529
+ """
530
+ highest: tuple[int, int, int] | None = None
531
+ highest_id = ""
532
+ paths = list(self._store.glob("*.json"))
533
+ paths.extend((self._store / _ARCHIVE_SUBDIR).glob("*.json"))
534
+ for path in paths:
535
+ if path.name.startswith("."):
536
+ continue
537
+ meta = self._load_file(path)
538
+ if meta is None or not meta.server_id:
539
+ continue
540
+ try:
541
+ order = _server_id_order(meta.server_id)
542
+ except ValueError:
543
+ # A hand-edited or truncated record must not stop the
544
+ # store from opening; it just does not advance anything.
545
+ logger.warning(
546
+ "keymaster: ignoring unparseable server_id %r on key %s",
547
+ meta.server_id,
548
+ meta.key_id,
549
+ )
550
+ continue
551
+ if highest is None or order > highest:
552
+ highest, highest_id = order, meta.server_id
553
+
554
+ if highest is None:
555
+ return
556
+ resumed = _next_server_id(highest_id)
557
+ with self._lock:
558
+ try:
559
+ requested_order = _server_id_order(requested_start)
560
+ except ValueError:
561
+ requested_order = None
562
+ if requested_order is None or _server_id_order(resumed) > requested_order:
563
+ self._server_id = resumed
564
+
497
565
  # ------------------------------------------------------------------
498
566
  # Core CRUD
499
567
  # ------------------------------------------------------------------
@@ -554,6 +622,101 @@ class Keymaster:
554
622
  return meta
555
623
  return None
556
624
 
625
+ # ------------------------------------------------------------------
626
+ # Reversal primitives
627
+ # ------------------------------------------------------------------
628
+ #
629
+ # The T1 API's auth undo/redo (POST /t1/auth/undo) reverses an
630
+ # operation by putting a key back the way it was. Each of these is one
631
+ # such inverse. They existed only as ``hasattr`` checks in the undo
632
+ # handler, which meant every undo answered 501 "this server's
633
+ # Keymaster cannot …" — a feature that could not work on any
634
+ # deployment, because no Keymaster had the methods.
635
+ #
636
+ # They are deliberately narrow. None of them creates or destroys a
637
+ # key, none changes a key's identity, and each writes exactly one
638
+ # field: an undo must land on a state the system could have reached
639
+ # forwards.
640
+
641
+ def restore_key(self, key_id: str, key_str: str) -> KeyMeta:
642
+ """Put previous key material back on an existing key.
643
+
644
+ Used to reverse a rotation. The key ID does not change — this is
645
+ the same record with its secret restored — so anything that
646
+ references the key by ID keeps working.
647
+ """
648
+ if not T1KeyGenerator.validate(key_str):
649
+ raise ValueError("Not a valid T1 key")
650
+ with self._lock:
651
+ meta = self._keys.get(key_id)
652
+ if meta is None:
653
+ raise KeyError(f"Key not found: {key_id!r}")
654
+ meta.key = key_str
655
+ self._save(meta)
656
+ logger.info("keymaster: restored key material on %s", key_id[:8])
657
+ return meta
658
+
659
+ def set_key_type(self, key_id: str, key_type: KeyType | str) -> KeyMeta:
660
+ """Change a key's type. Reverses a promotion."""
661
+ key_type = KeyType(key_type)
662
+ with self._lock:
663
+ meta = self._keys.get(key_id)
664
+ if meta is None:
665
+ raise KeyError(f"Key not found: {key_id!r}")
666
+ meta.key_type = key_type
667
+ self._save(meta)
668
+ logger.info("keymaster: set type of %s to %s", key_id[:8], key_type.value)
669
+ return meta
670
+
671
+ def set_scopes(self, key_id: str, scopes: Iterable[KeyScope | str]) -> KeyMeta:
672
+ """Replace a key's scope set. Reverses a scope change."""
673
+ resolved = {KeyScope(s) for s in scopes}
674
+ if not resolved:
675
+ raise ValueError("A key must keep at least one scope")
676
+ with self._lock:
677
+ meta = self._keys.get(key_id)
678
+ if meta is None:
679
+ raise KeyError(f"Key not found: {key_id!r}")
680
+ meta.scopes = resolved
681
+ self._save(meta)
682
+ logger.info("keymaster: set scopes of %s", key_id[:8])
683
+ return meta
684
+
685
+ def set_revoked(self, key_id: str, revoked: bool) -> KeyMeta:
686
+ """Revoke or un-revoke a key.
687
+
688
+ Un-revoking has to move the record back out of the archive, since
689
+ :meth:`revoke` archives rather than deletes — which is exactly what
690
+ makes the operation reversible at all.
691
+ """
692
+ if revoked:
693
+ with self._lock:
694
+ if key_id in self._keys:
695
+ self.revoke(key_id)
696
+ return self._load_file(self._archive_path(key_id)) # type: ignore[return-value]
697
+ archived = self._load_file(self._archive_path(key_id))
698
+ if archived is None:
699
+ raise KeyError(f"Key not found: {key_id!r}")
700
+ return archived
701
+
702
+ with self._lock:
703
+ if key_id in self._keys:
704
+ return self._keys[key_id]
705
+ meta = self._load_file(self._archive_path(key_id))
706
+ if meta is None:
707
+ raise KeyError(f"Key not found in the archive: {key_id!r}")
708
+ meta.active = True
709
+ meta.revoked_at = None
710
+ with self._lock:
711
+ self._keys[key_id] = meta
712
+ self._save(meta)
713
+ try:
714
+ self._archive_path(key_id).unlink()
715
+ except FileNotFoundError:
716
+ pass
717
+ logger.info("keymaster: un-revoked key %s", key_id[:8])
718
+ return meta
719
+
557
720
  def revoke(self, key_id: str, reason: str = "") -> None:
558
721
  """Revoke a key. It is archived but not deleted."""
559
722
  with self._lock:
@@ -234,6 +234,23 @@ class T1AuthService:
234
234
  details={"key_family": "T1", "accepted": self._accepted_families()},
235
235
  http_status=401,
236
236
  )
237
+ return self._authenticate_with_reload(key_str)
238
+
239
+ def _authenticate_with_reload(self, key_str: str) -> AuthContext:
240
+ """Authenticate a T1 key, refreshing the store once if it is unknown.
241
+
242
+ A key created after this process started is not in the in-memory
243
+ table yet, so the first lookup misses and a refresh is worth one
244
+ try before calling it invalid.
245
+
246
+ Shared with the T2 path deliberately. It used to live inline in
247
+ :meth:`validate_key`, which meant :meth:`_validate_t2` — reaching
248
+ the store through :meth:`_validate_uncached` — never refreshed at
249
+ all. A T1 key minted against a running server worked; the *same
250
+ key* presented in its T2 or T2S spelling was refused until the
251
+ server restarted, which is as confusing a failure as this codebase
252
+ can produce: the key is real, registered, and correctly typed.
253
+ """
237
254
  try:
238
255
  meta = self.gatekeeper.authenticate(key_str)
239
256
  except (ValueError, PermissionError):
@@ -270,7 +287,45 @@ class T1AuthService:
270
287
  raise T1APIError(T1ErrorCode.AUTH_INVALID_KEY, str(exc), http_status=401) from exc
271
288
 
272
289
  equivalent = T2KeyGenerator.to_t1(parsed)
273
- context = self._validate_uncached(equivalent)
290
+ try:
291
+ context = self._authenticate_with_reload(equivalent)
292
+ except T1APIError as exc:
293
+ # The underlying path only ever knew about T1 keys, so it says
294
+ # "Unknown or unregistered T1 key" to someone holding a T2S
295
+ # key — which reads as though the wrong *kind* of key was
296
+ # presented, when in fact the right kind simply is not in this
297
+ # server's key store.
298
+ #
299
+ # That distinction is the whole difficulty with a T2 key: it
300
+ # is a spelling of a T1 key, so it authenticates by being
301
+ # converted back and looked up. A T2 key generated on its own
302
+ # belongs to no key store and authenticates as nothing, no
303
+ # matter how well-formed it is. Saying so, and naming the
304
+ # command that mints a registered one, is the difference
305
+ # between a two-minute fix and an afternoon.
306
+ if exc.code is T1ErrorCode.AUTH_INVALID_KEY:
307
+ raise T1APIError(
308
+ T1ErrorCode.AUTH_INVALID_KEY,
309
+ f"This {parsed.family.value} key is well-formed but is not "
310
+ f"registered on this server.",
311
+ details={
312
+ "key_family": parsed.family.value,
313
+ "reason": "not_in_key_store",
314
+ "explanation": (
315
+ f"A {parsed.family.value} key is a spelling of a T1 key "
316
+ "rather than a separate credential: it is converted back "
317
+ "to its T1 form and looked up in the key store. A key "
318
+ "generated on its own is in no key store and authenticates "
319
+ "as nothing."
320
+ ),
321
+ "remedy": (
322
+ "Mint one on the server: "
323
+ f"gkey create -v {'v2short' if parsed.family is T2Type.T2S else 'v2'}"
324
+ ),
325
+ },
326
+ http_status=401,
327
+ ) from exc
328
+ raise
274
329
  context.t2_family = parsed.family.value
275
330
  context.t2_access_level = parsed.access_level
276
331
  context.t2_is_admin = parsed.is_admin
@@ -378,9 +378,48 @@ def require_hyperlink_admin(principal: HyperLinkPrincipal) -> HyperLinkPrincipal
378
378
  http_status=403,
379
379
  )
380
380
  if not principal.is_admin:
381
+ # A T2S key is never an administrator, and never can be: admin is
382
+ # carried by the password component in a T2 prefix, and the T2S
383
+ # format has no room for one — it is short enough to type, which
384
+ # is exactly why it must not carry administrative authority.
385
+ #
386
+ # Saying only "requires an admin key" sends that holder off to
387
+ # widen their key's scopes, which cannot work however many times
388
+ # they try. The property is in the format, not the grant.
389
+ family = ""
390
+ ctx = principal.auth_context
391
+ if ctx is not None:
392
+ family = ctx.t2_family
393
+ if family == "T2S":
394
+ raise T1APIError(
395
+ T1ErrorCode.AUTH_ADMIN_REQUIRED,
396
+ "A T2S key can never perform this operation. Pairing is admin-only, "
397
+ "and a T2S key is never an administrator by design.",
398
+ details={
399
+ "key_family": "T2S",
400
+ "reason": "t2s_is_never_admin",
401
+ "explanation": (
402
+ "Administrative authority rides on the password component of "
403
+ "a T2 prefix. A T2S key has no password component — it is "
404
+ "short enough to type by hand, which is why it must not carry "
405
+ "admin. Widening the underlying key's scopes will not change "
406
+ "this."
407
+ ),
408
+ "remedy": (
409
+ "Mint the pairing code on the PC with an admin key "
410
+ "(`waiter hyperlink pair`), then redeem the six-character "
411
+ "code on the phone. Use the T2S key for everything after "
412
+ "pairing."
413
+ ),
414
+ },
415
+ http_status=403,
416
+ )
381
417
  raise T1APIError(
382
418
  T1ErrorCode.AUTH_ADMIN_REQUIRED,
383
- "This HyperLink operation requires an admin T1 key.",
419
+ "This HyperLink operation requires an admin key.",
420
+ details={
421
+ "remedy": "gkey create --type admin --scopes admin,read,write",
422
+ },
384
423
  http_status=403,
385
424
  )
386
425
  return principal
@@ -1,8 +1,12 @@
1
1
  from __future__ import annotations
2
2
 
3
- from fastapi import APIRouter, Depends
3
+ import logging
4
+ from typing import Any
5
+
6
+ from fastapi import APIRouter, Depends, Request
4
7
 
5
8
  from ..auth import AuthContext, T1AuthService
9
+ from ..authhistory import AuthOp
6
10
  from ..deps import get_auth_context, get_auth_service, get_request_id, require_admin
7
11
  from ..schemas import (
8
12
  AdminRotateRequest,
@@ -13,6 +17,8 @@ from ..schemas import (
13
17
  ValidateKeyResponse,
14
18
  )
15
19
 
20
+ logger = logging.getLogger(__name__)
21
+
16
22
  router = APIRouter(prefix="/auth", tags=["auth"])
17
23
 
18
24
 
@@ -50,14 +56,63 @@ def issue_token(
50
56
  )
51
57
 
52
58
 
59
+ def _record_rotation(
60
+ request: Request,
61
+ *,
62
+ actor: str,
63
+ previous_key: str,
64
+ new_meta: Any,
65
+ previous_type: str = "",
66
+ ) -> None:
67
+ """Write a rotation into the auth history so it can be undone.
68
+
69
+ Without this, ``POST /t1/auth/undo`` has nothing to work with: the
70
+ history was only ever read, never written, so it was permanently
71
+ empty and every undo answered "nothing to undo". The endpoint
72
+ existed, the storage existed, and no operation ever put anything in
73
+ it.
74
+
75
+ Recorded against the *new* key ID, because that is the record the
76
+ inverse acts on — restoring the previous material onto it puts the
77
+ caller back where they were without changing any key ID, which is what
78
+ keeps references to the key valid across an undo.
79
+
80
+ Best-effort on purpose. The rotation has already happened and its new
81
+ key is in the response; failing the request now would tell the caller
82
+ their rotation failed when it did not, and lose the key with it.
83
+ """
84
+ history = getattr(request.app.state, "t1_auth_history", None)
85
+ if history is None:
86
+ return
87
+ payload = {"previous_key": previous_key, "new_key": new_meta.key}
88
+ if previous_type:
89
+ payload["previous_type"] = previous_type
90
+ payload["new_type"] = new_meta.key_type.value
91
+ try:
92
+ history.record(
93
+ AuthOp.ROTATE,
94
+ actor=actor,
95
+ target_key_id=new_meta.key_id,
96
+ payload=payload,
97
+ summary=f"rotated {new_meta.key_id[:8]}…",
98
+ )
99
+ except Exception: # noqa: BLE001
100
+ logger.warning("t1api.auth: could not record the rotation", exc_info=True)
101
+
102
+
53
103
  @router.post("/t1/rotate", response_model=RotateResponse)
54
104
  def rotate_own_key(
105
+ request: Request,
55
106
  ctx: AuthContext = Depends(get_auth_context),
56
107
  svc: T1AuthService = Depends(get_auth_service),
57
108
  request_id: str = Depends(get_request_id),
58
109
  ) -> RotateResponse:
59
110
  """A caller may always rotate the key/token they authenticated with."""
111
+ previous_key = ctx.key_meta.key
60
112
  new_meta = svc.rotate_own_key(ctx.key_id)
113
+ _record_rotation(
114
+ request, actor=ctx.key_id, previous_key=previous_key, new_meta=new_meta
115
+ )
61
116
  return RotateResponse(
62
117
  key_id=new_meta.key_id,
63
118
  key=new_meta.key,
@@ -70,15 +125,28 @@ def rotate_own_key(
70
125
 
71
126
  @router.post("/t1/admin/rotate", response_model=RotateResponse)
72
127
  def admin_rotate(
128
+ request: Request,
73
129
  body: AdminRotateRequest,
74
130
  ctx: AuthContext = Depends(get_auth_context),
75
131
  svc: T1AuthService = Depends(get_auth_service),
76
132
  request_id: str = Depends(get_request_id),
77
133
  ) -> RotateResponse:
78
134
  require_admin(ctx)
135
+ keymaster = getattr(request.app.state, "t1_keymaster", None)
136
+ target = keymaster.get(body.target_key_id) if keymaster is not None else None
137
+ previous_key = target.key if target is not None else ""
138
+ previous_type = target.key_type.value if target is not None else ""
79
139
  new_meta = svc.admin_rotate(
80
140
  requester=ctx, target_key_id=body.target_key_id, promote_to_admin=body.promote_to_admin
81
141
  )
142
+ if previous_key:
143
+ _record_rotation(
144
+ request,
145
+ actor=ctx.key_id,
146
+ previous_key=previous_key,
147
+ new_meta=new_meta,
148
+ previous_type=previous_type if body.promote_to_admin else "",
149
+ )
82
150
  return RotateResponse(
83
151
  key_id=new_meta.key_id,
84
152
  key=new_meta.key,
@@ -58,6 +58,31 @@ def _applier(request: Request):
58
58
  directory = getattr(request.app.state, "t1_key_directory", None)
59
59
 
60
60
  def apply(entry: Any, *, direction: str) -> None:
61
+ """Put a key back the way it was, or forward again.
62
+
63
+ Wrapped so that a key which no longer exists produces a refusal
64
+ rather than a bare 500. It is a reachable state, not a programming
65
+ error: the history outlives the keys it refers to, so undoing a
66
+ rotation whose key has since been revoked is an ordinary thing for
67
+ an operator to try, and "Internal Server Error" with no code and
68
+ no body is the least useful possible answer to it.
69
+ """
70
+ try:
71
+ _apply_inner(entry, direction=direction)
72
+ except KeyError as exc:
73
+ raise T1APIError(
74
+ T1ErrorCode.NOT_FOUND,
75
+ f"The key this {entry.op.value} applied to no longer exists, so it "
76
+ "cannot be reversed. The history entry is left in place.",
77
+ details={
78
+ "target_key_id": entry.target_key_id,
79
+ "op": entry.op.value,
80
+ "direction": direction,
81
+ },
82
+ http_status=409,
83
+ ) from exc
84
+
85
+ def _apply_inner(entry: Any, *, direction: str) -> None:
61
86
  payload = entry.payload
62
87
  # "undo" restores the previous value; "redo" re-applies the new
63
88
  # one. Choosing the field by direction is the whole of it — the
@@ -267,9 +267,14 @@ def parse_version(text: str) -> T1Version:
267
267
 
268
268
 
269
269
  #: The version this build of the T1 API implements.
270
- T1_VERSION = T1Version(api=1, major=0, year=2026, month=8, feature=1, fix=0)
271
- T1_VERSION_SHORT = T1_VERSION.short # "1.0.26.8.0.1"
272
- T1_VERSION_LONG = T1_VERSION.long # "1.0.2026.8.0.1"
270
+ #:
271
+ #: 1.0.2026.8.1.1 is a fix bump inside the 1.0.2026.8.1 feature release:
272
+ #: auth undo/redo now actually functions. It shipped with the history
273
+ #: never being written to and the Keymaster missing every method the
274
+ #: inverse needed, so the endpoints existed and could not work.
275
+ T1_VERSION = T1Version(api=1, major=0, year=2026, month=8, feature=1, fix=1)
276
+ T1_VERSION_SHORT = T1_VERSION.short # "1.0.26.8.1.1"
277
+ T1_VERSION_LONG = T1_VERSION.long # "1.0.2026.8.1.1"
273
278
 
274
279
  #: Oldest client this server still answers without a compatibility
275
280
  #: warning. Same generation, first release of it — everything from the
@@ -44,6 +44,14 @@ written against.
44
44
  """
45
45
  from __future__ import annotations
46
46
 
47
+ # Tracks the T1 API's own version (t1api/version.py), not the hypernix
48
+ # package's: the SDK implements an API contract, and its version should
49
+ # say which one.
50
+ # Derived from the API's own version rather than repeated. Importing it
51
+ # costs nothing the SDK was not already paying: hypernix.t1api.version is
52
+ # pure stdlib, so this does not drag the [t1api] server extra into a
53
+ # client that deliberately does without it.
54
+ from ..t1api.version import T1_VERSION_SHORT as _T1_VERSION_SHORT
47
55
  from .client import T1Client
48
56
  from .errors import (
49
57
  T1AuthError,
@@ -69,10 +77,7 @@ from .models import (
69
77
  )
70
78
  from .transport import HTTPTransport, Response, RetryPolicy, TLSConfig
71
79
 
72
- # Tracks the T1 API's own version (t1api/version.py), not the hypernix
73
- # package's: the SDK implements an API contract, and its version should
74
- # say which one.
75
- __sdk_version__ = "1.0.26.8.1.0"
80
+ __sdk_version__ = _T1_VERSION_SHORT
76
81
 
77
82
  __all__ = [
78
83
  "__sdk_version__",
@@ -25,6 +25,12 @@ new surfaces: ``waiter lmstudio`` (the LM Studio bridge),
25
25
  """
26
26
  from __future__ import annotations
27
27
 
28
- __waiter_version__ = "1.0.26.8.1.0"
28
+ # Derived, never typed. waiter's protocol version *is* the T1 API's, so a
29
+ # literal here is a second copy that drifts — which is exactly what
30
+ # happened to the T1 version in `waiter --help`, left advertising
31
+ # 1.0.26.8.0.1 two releases after the API had moved on.
32
+ from ..t1api.version import T1_VERSION_SHORT as _T1_VERSION_SHORT
33
+
34
+ __waiter_version__ = _T1_VERSION_SHORT
29
35
 
30
36
  __all__ = ["__waiter_version__"]
@@ -55,6 +55,8 @@ from concurrent.futures import ThreadPoolExecutor
55
55
  from dataclasses import dataclass, field
56
56
  from typing import Any
57
57
 
58
+ from ..t1api.version import T1_VERSION_SHORT
59
+
58
60
  logger = logging.getLogger(__name__)
59
61
 
60
62
  __all__ = [
@@ -359,7 +361,11 @@ class DiscoveredServer:
359
361
 
360
362
  def _get(url: str, timeout: float) -> tuple[int, str]:
361
363
  req = urllib.request.Request(
362
- url, headers={"Accept": "application/json", "User-Agent": "waiter-find/1.0.26.8.1.0"}
364
+ url,
365
+ headers={
366
+ "Accept": "application/json",
367
+ "User-Agent": f"waiter-find/{T1_VERSION_SHORT}",
368
+ },
363
369
  )
364
370
  try:
365
371
  with urllib.request.urlopen(req, timeout=timeout) as resp: # noqa: S310
@@ -621,7 +627,7 @@ def connect(
621
627
  "would be executing code chosen by the machine you are connecting to. "
622
628
  "Start it yourself if you trust this host."
623
629
  )
624
- if server.descriptor and not server.descriptor.supports_t1("1.0.26.8.1.0"):
630
+ if server.descriptor and not server.descriptor.supports_t1(T1_VERSION_SHORT):
625
631
  connection.notes.append(
626
632
  "This host advertises a T1 generation this client does not speak "
627
633
  f"({', '.join(server.descriptor.t1_versions)}); the connection may not work."
@@ -310,6 +310,7 @@ tests/test_quantize_v0703.py
310
310
  tests/test_ranges.py
311
311
  tests/test_shakers_and_torchcompat.py
312
312
  tests/test_snapshot_roundtrip.py
313
+ tests/test_t1_v1_0_26_8_1_1.py
313
314
  tests/test_t1_v1_0_26_core.py
314
315
  tests/test_t1_v1_0_26_http.py
315
316
  tests/test_t1api_auth.py
@@ -328,6 +329,7 @@ tests/test_t1api_modules.py
328
329
  tests/test_t1api_routing.py
329
330
  tests/test_t1api_security.py
330
331
  tests/test_t1api_servers.py
332
+ tests/test_t2s_errors.py
331
333
  tests/test_tupperware.py
332
334
  tests/test_tvtop_plus_plus_comprehensive.py
333
335
  tests/test_ups.py