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.
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/PKG-INFO +1 -1
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/pyproject.toml +1 -1
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/setup.cfg +1 -1
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/__init__.py +1 -1
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/hyperlink/__init__.py +3 -1
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/security/keymaster.py +163 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/auth.py +56 -1
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/deps.py +40 -1
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/auth.py +69 -1
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/authundo.py +25 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/version.py +8 -3
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1sdk/__init__.py +9 -4
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/waiter/__init__.py +7 -1
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/waiter/discovery.py +8 -2
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix.egg-info/SOURCES.txt +2 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_lint_regressions.py +43 -0
- hypernix-0.72.2.post5/tests/test_t1_v1_0_26_8_1_1.py +390 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1_v1_0_26_core.py +33 -19
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1_v1_0_26_http.py +2 -2
- hypernix-0.72.2.post5/tests/test_t2s_errors.py +325 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0721_api_waiter.py +14 -3
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Changelog.md +115 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Release-Timeline.md +11 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/T1-API.md +63 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/.github/workflows/build.yml +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/.github/workflows/ci.yml +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/.github/workflows/deploy-docs.yml +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/.github/workflows/ios.yml +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/.github/workflows/public-release.yml +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/.github/workflows/release.yml +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/.github/workflows/update-json-stats.yml +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/LICENSE +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/MANIFEST.in +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/README.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/assets/logo/Gemini_Generated_Image_nxfdm1nxfdm1nxfd-removebg-preview.png +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/assets/logo/Gemini_Generated_Image_nxfdm1nxfdm1nxfd.png +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/assets/logo.png +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/assets/logo1.png +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/curriculum_eval_v0_70_4.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/custom_arch.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/hypernix_run.json +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/quickstart.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/resilient_finetune_v0_70_4.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/run_hypernix.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/.env.example +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/API-EXAMPLES.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/Dockerfile +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/README.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/config/.gitkeep +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/docker-compose.yml +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/hypernix-t1api.service +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/nginx.conf +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/openapi.json +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/run_local.sh +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/t1api/run_tailscale.sh +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/train hypernix 1 5 gtx1080.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/train_hypernix_0_1_5_evaluator.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/train_hypernix_1_5_gtx1080.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/examples/upload_to_hub.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/pytest.ini +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/ruff.toml +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/README.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/apply_hypernix_fixes.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/autofix +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/autofix-B +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/autofix-E +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/autofix-F +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/autofix_scope.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/benchmark_v5.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/benchmark_v5s.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/benchmark_v6.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/install_deps.sh +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/install_macos_legacy.sh +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/measure_optimizer_memory.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/quantize_i7_7660u.sh +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/t1api_examples.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/scripts/update_json_stats.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/setup.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/__main__.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/bridge/__init__.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/bridge/lmstudio.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/chat/__init__.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/chat/cookbook.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/chat/countertop.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/chat/flour.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/chat/injection.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/chat/menu.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/__init__.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/blender.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/cardboard_box.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/cutting_board.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/food_processor.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/lunchbox.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/mediocre_fridge.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/pans.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/pepper_shaker.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/qa.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/salt_shaker.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/scavenger.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/sink.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/strainer.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/toaster.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/data/tupperware.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/evaluation/__init__.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/evaluation/espresso_maker.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/evaluation/industrial_range.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/evaluation/new_fridge.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/evaluation/new_range.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/evaluation/old_range.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/evaluation/vera.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/hyped_pro.js +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/hyperlink/discovery.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/hyperlink/files.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/hyperlink/hfdownload.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/hyperlink/hfmerge.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/hyperlink/pairing.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/hyperlink/sessions.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/__init__.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/assistant.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/cli.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/hyped.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/hyped_pro.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/hyped_pro_bridge.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/hyped_pro_core.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/hyped_pro_gui.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/hyped_pro_tools.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/noodle/__init__.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/noodle/agent.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/noodle/cli.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/noodle/hpo.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/noodle/providers.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/noodle/swarm.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/noodle/tools.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/noodle/validate.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/version_launcher.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/websearch.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/interfaces/wiki_cli.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/__init__.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/arch.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/download.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/generate.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/microwave.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/multilama.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/nano_nano.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/neo_oven.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/old_oven.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/stml.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/whisk.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/models/workshop.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/__init__.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/cctvtop.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/hyper_log.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/livestream.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/map.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/plasma.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/table.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/thermometer.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/tv.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/tvtop.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/monitoring/tvtop_plus_plus.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/optimizers/__init__.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/optimizers/optimizer_framework.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/optimizers/pressure_cooker.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/optimizers/pressure_cooker_v3.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/optimizers/pressure_cooker_v4.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/optimizers/pressure_cooker_v5.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/optimizers/pressure_cooker_v5s.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/optimizers/pressure_cooker_v6.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/optimizers/pressure_cooker_v6v.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/optimizers/sixbit.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/package-lock.json +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/package.json +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/py.typed +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/quant/__init__.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/quant/convert.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/quant/fetcher.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/quant/formats.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/quant/quantize.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/quant/steamroller.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/quant/steamroller_cli.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/quant/upload.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/scriptgen/__init__.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/scriptgen/app.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/scriptgen/cli.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/scriptgen/params.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/scriptgen/templates.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/scriptgen/theme.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/scriptgen/widgets.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/security/__init__.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/security/gatekeeper.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/security/gkey_cli.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/security/keyversions.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/security/t2keys.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/__init__.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/compactor.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/config.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/deps.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/dishwasher.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/doctor.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/ethanol.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/freezer.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/net.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/old_fridge.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/outage.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/pascal.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/pathfix.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/protect.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/release.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/torch_compat.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/ups.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/system/utils.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/__init__.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/app.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/audit.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/authhistory.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/backup.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/billing.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/config.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/cost.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/data/model_registry.example.json +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/data/routing_policies.example.json +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/db.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/deploy.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/errors.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/events.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/jobs.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/keys.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/modules.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/mtls.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/netpolicy.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/ratelimit.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/registry.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/__init__.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/audit.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/backup.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/billing.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/bridge.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/config.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/events.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/health.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/hyperlink.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/jobs.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/keys.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/models.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/modules.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/security.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/servers.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routers/usage.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/routing.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/schemas.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/security.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/servers.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/storage.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/transport.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1api/usage.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1sdk/client.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1sdk/errors.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1sdk/models.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/t1sdk/transport.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/timing/__init__.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/timing/bell.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/timing/coffee_maker.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/timing/smoke_alarm.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/timing/spinner.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/timing/timer.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/__init__.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/abbicus.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/apron.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/brewer.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/cake_pan.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/camouflage.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/compute_framework.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/deep_fryer.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/fizzle.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/instant_pot.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/lazy_suzan.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/mtp.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/recipe_book.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/smoker.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/training/train.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/tsconfig.json +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/waiter/cli.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/waiter/client.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/waiter/diagnose.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/waiter/local_config.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/waiter/smoke.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/src/hypernix/waiter/tui.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_alarms_and_presets.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_arch_mapping.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_assistant.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_autofix_scripts.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_cli_integration.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_coverage_beef.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_deps_and_windows.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_ethanol.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_fetcher.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_freezer.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_fridges.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_gkey_key_versions.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_hyped_pro_bridge_cancel.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_hyped_pro_t1api.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_install_pin.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_install_script.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_kitchen_v044.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_kitchen_v045.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_lazy_suzan.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_lunchbox.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_map.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_module_layout.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_neo_oven.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_neo_oven_generation.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_new_archs_v035.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_nix_fallback.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_old_oven.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_pathfix.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_pressure_cooker_v048.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_pressure_cooker_v3.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_pressure_cooker_v6.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_quantize_v0703.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_ranges.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_shakers_and_torchcompat.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_snapshot_roundtrip.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_auth.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_beta3_core.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_beta3_http.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_beta3_security.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_beta4_usage_report.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_billing.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_core.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_events.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_example_scripts.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_http.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_http_beta2.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_jobs.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_modules.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_routing.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_security.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_t1api_servers.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_tupperware.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_tvtop_plus_plus_comprehensive.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_ups.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v031_chat_and_archs.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v047_deep_fryer_cake_pan_presets.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v050.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v051.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v051_1.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v051_3.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v051_4.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v052_5.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v052_6.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v060.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v061_1.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v061_2.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v061_b1.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0703_additional.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0704_features.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0704_tvtop_plus_plus.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0704b11_features.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0704b12_cctvtop.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0705_all.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0710_gatekeeper_keymaster.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0711_border_fix.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0712_hyped_countertop.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0714_config_provider_keys.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0714_cpu_presets.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0714_hyped_pro_bridge.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0714_hyped_pro_core.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0714_hyped_pro_launcher.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0714_hyped_pro_tools.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0714_multilama.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0721_modules.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_v0721_t2_keys.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_vera.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_version_launcher.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_waiter.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/tests/test_waiter_diagnose.py +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Abbicus.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Alarms.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Apron.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Architectures.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Bell.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Blender.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/CLI.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/CakePan.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Camouflage.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/CoffeeMaker.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Convert.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Cookbook.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Countertop.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/CuttingBoard.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Dashboards.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/DeepFryer.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Download.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/EspressoMaker.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Flour.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/FoodProcessor.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Frameworks.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Freezer.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Fridges.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Home.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/HuggingFace-Models.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/HyperLog.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Kitchen.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Lunchbox.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/MTP.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Menu.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Microwave.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Optimizers.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Ovens.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Pans.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Pascal.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/PipelineMechanics.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Pressure-Cooker-V3.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Pressure-Cooker-V4.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Pressure-Cooker-V5.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Pressure-Cooker-V6.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Quantization.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Ranges.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/RecipeBook.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Roadmap.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/STML.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Scavenger.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Shakers.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Smoker.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/T1-API-Security-Checklist.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Toaster.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Training.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Tupperware.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Vera.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Waiter-TUI.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Whisk.md +0 -0
- {hypernix-0.72.2.post3 → hypernix-0.72.2.post5}/wiki/Workshop.md +0 -0
- {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.
|
|
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.
|
|
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" }
|
|
@@ -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__ =
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
271
|
-
|
|
272
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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(
|
|
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
|