nerdit 0.7.2__tar.gz → 0.8.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nerdit-0.7.2 → nerdit-0.8.0}/PKG-INFO +4 -4
- {nerdit-0.7.2 → nerdit-0.8.0}/README.md +3 -3
- {nerdit-0.7.2 → nerdit-0.8.0}/pyproject.toml +1 -1
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/__init__.py +1 -1
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/client.py +10 -1
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/dev.py +7 -3
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/routes.py +9 -2
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/share.py +39 -2
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/display.py +22 -10
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/cutover.py +27 -14
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/proxy/manager.py +23 -1
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/services.py +6 -1
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/_resources.py +4 -2
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/domains.py +13 -2
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/proxy.py +3 -1
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/share.py +106 -18
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/system.py +4 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/exposure.py +27 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/proxy.py +9 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/views/hosted.py +16 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/views/service.py +7 -1
- nerdit-0.7.2/src/nerdit/daemon/web/dist/assets/index-BiZkV8Cy.js → nerdit-0.8.0/src/nerdit/daemon/web/dist/assets/index-BbpL4BJf.js +23 -23
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/dist/index.html +1 -1
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/api/types.ts +8 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/ServicePublicUrl.tsx +10 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/ServiceShareCard.test.tsx +17 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/ServiceShareCard.tsx +7 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/settings/RoutesCard.tsx +19 -3
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/lib/format.test.ts +11 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/lib/format.ts +8 -1
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/db/database.py +9 -3
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/db/queries/domains.py +15 -4
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/db/queries/services.py +4 -1
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/db/queries/shares.py +54 -7
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/db/rows.py +4 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/mcp/tools/exposure.py +22 -1
- {nerdit-0.7.2 → nerdit-0.8.0}/.gitignore +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/LICENSE +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/NOTICE +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/__main__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/__init__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/app.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/checks.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/__init__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/apply.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/backup.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/capabilities.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/check_deps.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/config.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/connect.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/daemon.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/db.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/deploy.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/diagnose.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/doctor.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/domains.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/events.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/exit.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/init.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/license.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/link.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/logs.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/mcp.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/models.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/projects.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/proxy.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/secrets.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/serve.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/services.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/store.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/system.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/token.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/trust.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/uninstall.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/update.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/commands/vars.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/cli/upload.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/config/__init__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/config/app_config.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/config/app_templates/__init__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/config/app_templates/builtin.json +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/config/app_templates/loader.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/config/build.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/config/defaults.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/config/project.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/config/redaction.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/config/settings.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/config/store.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/__init__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/app_build.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/backup.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/bindings/__init__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/bindings/registry.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/bindings/secretref.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/builder.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/data/__init__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/data/backend.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/data/binding.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/data/controller.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/deploy_state.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/discovery.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/dns.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/eventlog.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/events.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/gitsource.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/gitwatch.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/health.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/jobconfig.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/launch.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/license.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/link/__init__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/link/apps.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/link/capability.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/link/client.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/link/frames.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/link/hosted.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/link/identity.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/link/manager.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/link/mux.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/models/__init__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/models/backend.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/models/binding.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/models/controller.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/monitor.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/node_packages.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/node_runtime.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/notify.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/project_identity.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/proxy/__init__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/proxy/admin.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/proxy/certs.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/proxy/domains.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/proxy/edgeauth.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/proxy/routing.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/proxy/supervisor.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/proxy/tls.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/remediation_settle.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/resources/__init__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/resources/controller.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/retention.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/runtime/__init__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/runtime/container.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/runtime/docker.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/runtime/protocol.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/runtime/stub.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/sandbox.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/secrets.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/sweeper.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/variables.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/volumes.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/workload.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/core/workspaces.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/__init__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/appfactory.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/audit.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/auth.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/bodylimit.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/bootstrap.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/deploy_pipeline.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/errors.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/idempotency.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/imagegc.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/lifecycle.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/limits.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/middleware.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/project_delegation.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/remediation.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/__init__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/app_config.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/app_templates.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/audit.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/auth.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/cluster.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/config.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/databases.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/deploy.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/events.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/gpus.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/health.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/images.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/license.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/link.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/models.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/projects.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/secrets.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/service_diagnose.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/service_logs_stream.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/service_run.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/service_stats.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/service_wait.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/services.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/tokens.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/routes/workspaces.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/__init__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/_base.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/audit.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/cluster.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/config.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/databases.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/deploy.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/events.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/gpus.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/health.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/license.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/link.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/models.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/service_diagnose.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/service_purge.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/service_run.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/service_stats.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/service_wait.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/services.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/system.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/tokens.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/schemas/workspaces.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/secret_scope.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/server.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/service_purge.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/sse.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/sweeps.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/uploads.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/views/__init__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/dist/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/dist/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/dist/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/dist/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/dist/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/dist/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/dist/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/dist/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/dist/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/dist/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/dist/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/dist/assets/index-CLfzcEzV.css +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/eslint.config.js +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/index.html +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/package-lock.json +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/package.json +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/playwright.config.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/postcss.config.js +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/api/auditStream.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/api/client.test.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/api/client.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/api/clusterEvents.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/api/queries.test.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/api/queries.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/CommandPalette.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/ConfigurePanel.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/DaemonStatusBanner.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/DeployDialog.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/DeployProgress.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/DiagnosePanel.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/Dropzone.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/ErrorBoundary.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/SecretsPanel.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/ServiceLogsPanel.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/TemplateDeployDialog.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/ToastViewport.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/UnlinkedBanner.test.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/UnlinkedBanner.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/bindings/AiEndpointFields.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/bindings/BindingSwitch.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/bindings/GenericBindingsPanel.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/bindings/KeyFlow.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/bindings/sections.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/bindings/useBindingDraft.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/settings/AppearanceCard.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/settings/DiskCard.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/settings/DoctorCard.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/settings/GpuCard.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/settings/HostnameCard.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/settings/ProxyStatusCard.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/ui.test.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/components/ui.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/lib/aiProviders.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/lib/analytics.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/lib/apiErrors.test.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/lib/apiErrors.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/lib/auth.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/lib/bindings.test.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/lib/bindings.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/lib/deployPhase.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/lib/projects.test.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/lib/projects.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/lib/sse.test.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/lib/sse.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/lib/status.test.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/lib/status.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/lib/theme.test.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/lib/theme.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/main.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/pages/Audit.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/pages/Databases.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/pages/Login.test.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/pages/Login.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/pages/Models.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/pages/ProjectDetail.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/pages/ProjectPage.test.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/pages/ProjectPage.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/pages/ProjectPolling.test.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/pages/Projects.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/pages/ServiceRedirect.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/pages/Settings.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/pages/Tokens.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/shell/AppShell.tsx +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/shell/navItems.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/state/toastStore.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/src/styles/globals.css +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/tailwind.config.js +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/tests/e2e/01-login-and-overview.spec.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/tests/e2e/05-services.spec.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/tests/e2e/06-models.spec.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/tests/e2e/07-audit.spec.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/tests/e2e/08-secrets.spec.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/tests/e2e/10-settings.spec.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/tests/e2e/11-configure.spec.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/tests/e2e/12-deploy.spec.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/tests/e2e/13-bindings.spec.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/tests/e2e/14-responsive-shell.spec.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/tests/e2e/17-projects.spec.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/tests/e2e/18-navigation.spec.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/tests/e2e/19-project-page.spec.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/tests/e2e/20-command-palette.spec.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/tests/e2e/21-tokens.spec.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/tests/e2e/22-system-cards.spec.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/tests/e2e/fixtures.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/tsconfig.json +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/tsconfig.tsbuildinfo +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/daemon/web/vite.config.ts +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/db/__init__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/db/enums.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/db/models.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/db/queries/__init__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/db/queries/_base.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/db/queries/audit.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/db/queries/endpoints.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/db/queries/events.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/db/queries/gpus.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/db/queries/idempotency.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/db/queries/logs.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/db/queries/projects.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/db/queries/secret_claims.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/db/queries/service_config.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/db/queries/tokens.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/db/queries/workloads.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/mcp/__init__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/mcp/errors.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/mcp/server.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/mcp/tools/__init__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/mcp/tools/_shared.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/mcp/tools/cluster.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/mcp/tools/config.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/mcp/tools/databases.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/mcp/tools/deploy.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/mcp/tools/models.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/mcp/tools/projects.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/mcp/tools/secrets.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/mcp/tools/services.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/mcp/tools/system.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/mcp/tools/workspaces.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/mcp/transport.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/utils/__init__.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/utils/certs.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/utils/disk.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/utils/frozen.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/utils/fs.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/utils/ids.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/utils/install_layout.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/utils/logging.py +0 -0
- {nerdit-0.7.2 → nerdit-0.8.0}/src/nerdit/utils/names.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: nerdit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: The local AI PaaS — deploy and operate apps on your own hardware, with first-class local AI
|
|
5
5
|
Project-URL: Homepage, https://github.com/nerdit-ai/nerdit
|
|
6
6
|
Project-URL: Repository, https://github.com/nerdit-ai/nerdit
|
|
@@ -272,10 +272,10 @@ Questions or feedback: [feedback@nerdit.ai](mailto:feedback@nerdit.ai).
|
|
|
272
272
|
|
|
273
273
|
## License
|
|
274
274
|
|
|
275
|
-
Apache-2.0, see [LICENSE](https://github.com/nerdit-ai/nerdit/blob/v0.
|
|
276
|
-
are not covered by the code license, see [NOTICE](https://github.com/nerdit-ai/nerdit/blob/v0.
|
|
275
|
+
Apache-2.0, see [LICENSE](https://github.com/nerdit-ai/nerdit/blob/v0.8.0/LICENSE). "Nerdit" and the logo are trademarks and
|
|
276
|
+
are not covered by the code license, see [NOTICE](https://github.com/nerdit-ai/nerdit/blob/v0.8.0/NOTICE).
|
|
277
277
|
|
|
278
278
|
## Contributing
|
|
279
279
|
|
|
280
|
-
Issues and pull requests are welcome. [CONTRIBUTING.md](https://github.com/nerdit-ai/nerdit/blob/v0.
|
|
280
|
+
Issues and pull requests are welcome. [CONTRIBUTING.md](https://github.com/nerdit-ai/nerdit/blob/v0.8.0/CONTRIBUTING.md)
|
|
281
281
|
explains how contributions land in releases.
|
|
@@ -213,10 +213,10 @@ Questions or feedback: [feedback@nerdit.ai](mailto:feedback@nerdit.ai).
|
|
|
213
213
|
|
|
214
214
|
## License
|
|
215
215
|
|
|
216
|
-
Apache-2.0, see [LICENSE](https://github.com/nerdit-ai/nerdit/blob/v0.
|
|
217
|
-
are not covered by the code license, see [NOTICE](https://github.com/nerdit-ai/nerdit/blob/v0.
|
|
216
|
+
Apache-2.0, see [LICENSE](https://github.com/nerdit-ai/nerdit/blob/v0.8.0/LICENSE). "Nerdit" and the logo are trademarks and
|
|
217
|
+
are not covered by the code license, see [NOTICE](https://github.com/nerdit-ai/nerdit/blob/v0.8.0/NOTICE).
|
|
218
218
|
|
|
219
219
|
## Contributing
|
|
220
220
|
|
|
221
|
-
Issues and pull requests are welcome. [CONTRIBUTING.md](https://github.com/nerdit-ai/nerdit/blob/v0.
|
|
221
|
+
Issues and pull requests are welcome. [CONTRIBUTING.md](https://github.com/nerdit-ai/nerdit/blob/v0.8.0/CONTRIBUTING.md)
|
|
222
222
|
explains how contributions land in releases.
|
|
@@ -879,17 +879,26 @@ class NerditClient:
|
|
|
879
879
|
*,
|
|
880
880
|
access: str = "private",
|
|
881
881
|
consent: bool = False,
|
|
882
|
+
preserve_existing: bool = False,
|
|
883
|
+
hosted_only: bool | None = None,
|
|
882
884
|
idempotency_key: str | None = None,
|
|
883
885
|
) -> dict:
|
|
884
886
|
"""Share a service; requires an idempotency key.
|
|
885
887
|
|
|
886
888
|
The daemon validates entitlement, consent, link state, service kind and
|
|
887
889
|
label length. Send values unchanged so client validation cannot drift.
|
|
890
|
+
``preserve_existing`` and ``hosted_only`` travel only when set, so an
|
|
891
|
+
older daemon (``extra="forbid"``) still accepts the plain body.
|
|
888
892
|
"""
|
|
893
|
+
body: dict[str, object] = {"access": access, "consent": consent}
|
|
894
|
+
if preserve_existing:
|
|
895
|
+
body["preserve_existing"] = True
|
|
896
|
+
if hosted_only is not None:
|
|
897
|
+
body["hosted_only"] = hosted_only
|
|
889
898
|
return await self._request_json(
|
|
890
899
|
"PUT",
|
|
891
900
|
f"{self._base_url}/api/services/{self._segment(name)}/share",
|
|
892
|
-
json=
|
|
901
|
+
json=body,
|
|
893
902
|
idempotency_key=idempotency_key,
|
|
894
903
|
timeout=15.0,
|
|
895
904
|
)
|
|
@@ -19,6 +19,7 @@ import typer
|
|
|
19
19
|
from rich.markup import escape
|
|
20
20
|
|
|
21
21
|
from nerdit.cli.display import (
|
|
22
|
+
_hosted_only,
|
|
22
23
|
_plain,
|
|
23
24
|
console,
|
|
24
25
|
display_deploy_result,
|
|
@@ -136,9 +137,12 @@ def _cutover_warning(name: str, service: dict | None, cutover: bool | None) -> l
|
|
|
136
137
|
reason = "only apps (kind = service) are cutover-eligible"
|
|
137
138
|
elif (service.get("gpu_count") or 0) > 0:
|
|
138
139
|
reason = "GPU services keep the same-port swap (two containers cannot hold one GPU)"
|
|
139
|
-
elif
|
|
140
|
-
service.get("
|
|
141
|
-
|
|
140
|
+
elif (
|
|
141
|
+
service.get("status") in ("running", "degraded")
|
|
142
|
+
and not (endpoint := service.get("endpoint") or {}).get("public_url")
|
|
143
|
+
# A locked app's null public_url is by design, not a missing route.
|
|
144
|
+
and not _hosted_only(endpoint)
|
|
145
|
+
):
|
|
142
146
|
reason = "no proxy route — zero-downtime redeploys need [proxy].enabled"
|
|
143
147
|
else:
|
|
144
148
|
return []
|
|
@@ -25,8 +25,15 @@ def _route_cell(route: object) -> str:
|
|
|
25
25
|
return _plain(route)
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
def _live_cell(live: object) -> str:
|
|
28
|
+
def _live_cell(live: object, reason: object = None) -> str:
|
|
29
29
|
"""Render the live-Caddy annotation; `None` ⇒ `-` (unknown, not "no")."""
|
|
30
|
+
if reason == "hosted_only":
|
|
31
|
+
# `None` is still unknown here: the lock is an intent, and the proxy may
|
|
32
|
+
# keep serving a route the deregistration never reached.
|
|
33
|
+
if live is None:
|
|
34
|
+
return "hosted only [yellow](proxy table unreadable)[/yellow]"
|
|
35
|
+
still_live = isinstance(live, dict) and live.get("registered")
|
|
36
|
+
return "hosted only" + (" [yellow](route still live)[/yellow]" if still_live else "")
|
|
30
37
|
if live is None:
|
|
31
38
|
return "-"
|
|
32
39
|
if not isinstance(live, dict):
|
|
@@ -75,7 +82,7 @@ async def _routes_async(*, limit: int, cursor: str | None) -> int:
|
|
|
75
82
|
_route_cell(item.get("route")),
|
|
76
83
|
_plain(item.get("public_url")),
|
|
77
84
|
_plain(item.get("host_port")),
|
|
78
|
-
_live_cell(item.get("live")),
|
|
85
|
+
_live_cell(item.get("live"), item.get("reason")),
|
|
79
86
|
)
|
|
80
87
|
console.print(table)
|
|
81
88
|
|
|
@@ -30,6 +30,16 @@ _STATE_NOTES = {
|
|
|
30
30
|
),
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
#: (Lot 5) ``local_routes`` token → the line printed for a hosted-only share.
|
|
34
|
+
_LOCAL_ROUTES_NOTES = {
|
|
35
|
+
"absent": "local routes: absent (hosted only)",
|
|
36
|
+
"present": "local routes: present: purge pending, retry in a few seconds",
|
|
37
|
+
"unknown": (
|
|
38
|
+
"local routes: unknown: proxy unreadable, or the daemon is reachable "
|
|
39
|
+
"without a token (see nerdit doctor)"
|
|
40
|
+
),
|
|
41
|
+
}
|
|
42
|
+
|
|
33
43
|
|
|
34
44
|
def _render_share(name: str, result: Any, *, verb: str) -> None:
|
|
35
45
|
"""Print one share as `<verb> <name> (<access>): <url>` + any state note."""
|
|
@@ -52,6 +62,11 @@ def _render_share(name: str, result: Any, *, verb: str) -> None:
|
|
|
52
62
|
hint = origin.get("hint")
|
|
53
63
|
if isinstance(hint, str) and hint:
|
|
54
64
|
console.print(f"[yellow]origin — {_plain(hint)}[/yellow]")
|
|
65
|
+
if result.get("hosted_only") is True:
|
|
66
|
+
routes = result.get("local_routes")
|
|
67
|
+
note = _LOCAL_ROUTES_NOTES.get(routes) if isinstance(routes, str) else None
|
|
68
|
+
line = note or f"local routes: {_plain(routes)}"
|
|
69
|
+
console.print(line if routes == "absent" else f"[yellow]{line}[/yellow]")
|
|
55
70
|
|
|
56
71
|
|
|
57
72
|
def share(
|
|
@@ -77,12 +92,31 @@ def share(
|
|
|
77
92
|
"--show",
|
|
78
93
|
help="Print the current share instead of changing it.",
|
|
79
94
|
),
|
|
95
|
+
hosted_only: bool | None = typer.Option(
|
|
96
|
+
None,
|
|
97
|
+
"--hosted-only/--local-route",
|
|
98
|
+
help=(
|
|
99
|
+
"--hosted-only locks the app to its hosted URL: this machine's proxy "
|
|
100
|
+
"keeps no local route for it. --local-route unlocks and restores the "
|
|
101
|
+
"local routes (needs the link; offline, nerdit unshare <app> also "
|
|
102
|
+
"restores them). Without --public, an existing public share stays public."
|
|
103
|
+
),
|
|
104
|
+
),
|
|
80
105
|
) -> None:
|
|
81
106
|
"""Share a deployed app at a hosted URL through this node's cloud link."""
|
|
82
|
-
|
|
107
|
+
if show and hosted_only is not None:
|
|
108
|
+
raise typer.BadParameter(
|
|
109
|
+
"--show prints the share; it cannot be combined with --hosted-only/--local-route",
|
|
110
|
+
param_hint="--show",
|
|
111
|
+
)
|
|
112
|
+
asyncio.run(
|
|
113
|
+
_share_async(name, public=public, consent=consent, show=show, hosted_only=hosted_only)
|
|
114
|
+
)
|
|
83
115
|
|
|
84
116
|
|
|
85
|
-
async def _share_async(
|
|
117
|
+
async def _share_async(
|
|
118
|
+
name: str, *, public: bool, consent: bool, show: bool, hosted_only: bool | None = None
|
|
119
|
+
) -> None:
|
|
86
120
|
from nerdit.cli.client import get_configured_client
|
|
87
121
|
|
|
88
122
|
client = get_configured_client()
|
|
@@ -97,6 +131,9 @@ async def _share_async(name: str, *, public: bool, consent: bool, show: bool) ->
|
|
|
97
131
|
name,
|
|
98
132
|
access="public" if public else "private",
|
|
99
133
|
consent=consent,
|
|
134
|
+
# (Lot 5) A lock flag alone must not downgrade a public share.
|
|
135
|
+
preserve_existing=hosted_only is not None and not public,
|
|
136
|
+
hosted_only=hosted_only,
|
|
100
137
|
idempotency_key=uuid4().hex,
|
|
101
138
|
)
|
|
102
139
|
except Exception as exc: # noqa: BLE001 — rendered for the user
|
|
@@ -223,6 +223,14 @@ def display_gpu_table(gpus: list[dict]) -> None:
|
|
|
223
223
|
console.print(table)
|
|
224
224
|
|
|
225
225
|
|
|
226
|
+
def _hosted_only(endpoint: dict) -> bool:
|
|
227
|
+
"""(Lot 5) A locked app: no client shows its loopback ``endpoint.url``."""
|
|
228
|
+
return any(
|
|
229
|
+
isinstance(entry, dict) and entry.get("hosted_only") is True
|
|
230
|
+
for entry in endpoint.get("public_urls") or []
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
|
|
226
234
|
def display_service_table(services: list[dict]) -> None:
|
|
227
235
|
"""Display a Rich table of services (name, status, restarts, GPUs, URL)."""
|
|
228
236
|
table = Table(title="Services")
|
|
@@ -244,11 +252,14 @@ def display_service_table(services: list[dict]) -> None:
|
|
|
244
252
|
|
|
245
253
|
endpoint = svc.get("endpoint") or {}
|
|
246
254
|
host_port = endpoint.get("host_port")
|
|
247
|
-
|
|
248
|
-
endpoint.get("public_url")
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
255
|
+
if _hosted_only(endpoint):
|
|
256
|
+
url = endpoint.get("public_url") or "-"
|
|
257
|
+
else:
|
|
258
|
+
url = (
|
|
259
|
+
endpoint.get("public_url")
|
|
260
|
+
or endpoint.get("url")
|
|
261
|
+
or (f"127.0.0.1:{host_port}" if host_port else "-")
|
|
262
|
+
)
|
|
252
263
|
|
|
253
264
|
table.add_row(
|
|
254
265
|
_plain(svc.get("name", "")),
|
|
@@ -433,12 +444,13 @@ def display_service_submitted(service: dict) -> None:
|
|
|
433
444
|
console.print(f" Status: {_plain(service.get('status'))}")
|
|
434
445
|
endpoint = service.get("endpoint") or {}
|
|
435
446
|
public_url = endpoint.get("public_url")
|
|
447
|
+
local = None if _hosted_only(endpoint) else endpoint.get("url")
|
|
436
448
|
if public_url:
|
|
437
449
|
console.print(f" URL: {_plain(public_url)}")
|
|
438
|
-
if
|
|
439
|
-
console.print(f" Local: {_plain(
|
|
440
|
-
elif
|
|
441
|
-
console.print(f" URL: {_plain(
|
|
450
|
+
if local:
|
|
451
|
+
console.print(f" Local: {_plain(local)}")
|
|
452
|
+
elif local:
|
|
453
|
+
console.print(f" URL: {_plain(local)}")
|
|
442
454
|
|
|
443
455
|
|
|
444
456
|
def display_deploy_result(
|
|
@@ -452,7 +464,7 @@ def display_deploy_result(
|
|
|
452
464
|
console.print(f"[green]{heading}:[/green] {name}")
|
|
453
465
|
console.print(f" Status: {_plain(service.get('status'))}")
|
|
454
466
|
endpoint = service.get("endpoint") or {}
|
|
455
|
-
url = endpoint.get("public_url") or endpoint.get("url")
|
|
467
|
+
url = endpoint.get("public_url") or (None if _hosted_only(endpoint) else endpoint.get("url"))
|
|
456
468
|
if url:
|
|
457
469
|
console.print(f" URL: {_plain(url)}")
|
|
458
470
|
for hint in service.get("hints") or []:
|
|
@@ -612,8 +612,18 @@ class CutoverManager:
|
|
|
612
612
|
# and this call needs nothing but the ids. The domain rows are read
|
|
613
613
|
# here, at commit time, so a domain bound during the verify window is
|
|
614
614
|
# included and one removed during it is not.
|
|
615
|
+
# Lot 5: a hosted-only app has no local route, so there is no dial to
|
|
616
|
+
# repoint or verify; it is promoted on its probe alone (f1 still runs:
|
|
617
|
+
# the hosted resolver dials `active_host_port`). A lock landing after
|
|
618
|
+
# this read makes `register` refuse, the dial never converges, and the
|
|
619
|
+
# cutover settles `repoint_failure` with blue serving and no route.
|
|
620
|
+
locked = await queries.is_hosted_only(name)
|
|
615
621
|
domain_rows = await queries.get_service_domains(name)
|
|
616
|
-
caddy_ids
|
|
622
|
+
caddy_ids: tuple[str, ...] = (
|
|
623
|
+
()
|
|
624
|
+
if locked
|
|
625
|
+
else (_route_id(name), *(_domain_route_id(name, r.domain) for r in domain_rows))
|
|
626
|
+
)
|
|
617
627
|
# The repoint REBUILDS the whole route object,
|
|
618
628
|
# so the row's `edge_auth` must ride along or every cutover commit of a
|
|
619
629
|
# protected service would strip its auth handler — and `_await_dial`
|
|
@@ -623,19 +633,20 @@ class CutoverManager:
|
|
|
623
633
|
# and the cutover settles `repoint_failure` with blue restored — the
|
|
624
634
|
# route is then withheld until the secret resolves. Posture beats
|
|
625
635
|
# availability.
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
636
|
+
if not locked:
|
|
637
|
+
await proxy.register(
|
|
638
|
+
name,
|
|
639
|
+
green_port,
|
|
640
|
+
edge_auth=parse_job_config(job).get("edge_auth"),
|
|
641
|
+
project_id=job.project_id,
|
|
642
|
+
with_domains=True,
|
|
643
|
+
# The SAME snapshot `caddy_ids` was derived from, never a second
|
|
644
|
+
# read: a `DELETE` landing between two reads would leave a removed
|
|
645
|
+
# id in the awaited set that nothing ever writes, and
|
|
646
|
+
# `_await_dials` would burn its whole budget and unwind a healthy
|
|
647
|
+
# green. The removed route is torn down by the next reconcile tick.
|
|
648
|
+
domains=[r.domain for r in domain_rows],
|
|
649
|
+
)
|
|
639
650
|
if not await self._await_dials(caddy_ids, green_port):
|
|
640
651
|
await self._settle_repoint_failure(
|
|
641
652
|
job, version, green_id=green_id, name=name, caddy_ids=caddy_ids
|
|
@@ -739,6 +750,8 @@ class CutoverManager:
|
|
|
739
750
|
One deadline covers the whole set (`cutover_repoint_timeout_s`), not
|
|
740
751
|
one per id.
|
|
741
752
|
"""
|
|
753
|
+
if not caddy_ids:
|
|
754
|
+
return True # lot 5: a hosted-only app has no route to verify
|
|
742
755
|
proxy = self._c._proxy
|
|
743
756
|
assert proxy is not None
|
|
744
757
|
expected = f"127.0.0.1:{port}"
|
|
@@ -22,7 +22,7 @@ import time
|
|
|
22
22
|
from collections.abc import Callable, Sequence
|
|
23
23
|
from enum import Enum
|
|
24
24
|
from pathlib import Path
|
|
25
|
-
from typing import TYPE_CHECKING, Any
|
|
25
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
26
26
|
from urllib.parse import urlsplit
|
|
27
27
|
|
|
28
28
|
from nerdit.config.defaults import DEFAULT_HOST, DEFAULT_PORT
|
|
@@ -1089,6 +1089,11 @@ class ProxyManager(CaddySupervisorMixin, CaddyTlsMixin):
|
|
|
1089
1089
|
return
|
|
1090
1090
|
new_dial = f"127.0.0.1:{host_port}"
|
|
1091
1091
|
try:
|
|
1092
|
+
# Lot 5: a hosted-only app has no local route. Inside the try, so a
|
|
1093
|
+
# failed lock read writes nothing (fail closed).
|
|
1094
|
+
if await self._queries.is_hosted_only(service_name):
|
|
1095
|
+
await self._deregister_unlocked(service_name)
|
|
1096
|
+
return
|
|
1092
1097
|
try:
|
|
1093
1098
|
spec = await self._build_route_off_loop(
|
|
1094
1099
|
service_name, host_port, load_edge_auth(edge_auth), project_id
|
|
@@ -1240,6 +1245,23 @@ class ProxyManager(CaddySupervisorMixin, CaddyTlsMixin):
|
|
|
1240
1245
|
except Exception:
|
|
1241
1246
|
logger.warning("[proxy] deregister failed for %s", service_name, exc_info=True)
|
|
1242
1247
|
|
|
1248
|
+
async def local_route_state(self, service_name: str) -> Literal["absent", "present", "unknown"]:
|
|
1249
|
+
"""Observe whether Caddy's live table holds any route of `service_name`.
|
|
1250
|
+
|
|
1251
|
+
Asks the admin API even when the proxy is disabled: a leftover Caddy may
|
|
1252
|
+
still serve. Unreadable is `unknown`, except a disabled proxy with no live
|
|
1253
|
+
pid, which has nothing that could serve (`absent`).
|
|
1254
|
+
"""
|
|
1255
|
+
if self.enabled and not self._available:
|
|
1256
|
+
return "unknown"
|
|
1257
|
+
try:
|
|
1258
|
+
live = await self._admin.live_routes()
|
|
1259
|
+
except Exception:
|
|
1260
|
+
live = None
|
|
1261
|
+
if live is None:
|
|
1262
|
+
return "unknown" if self.enabled or self._pid_alive() else "absent"
|
|
1263
|
+
return "present" if any(_split_route_id(r)[0] == service_name for r in live) else "absent"
|
|
1264
|
+
|
|
1243
1265
|
# -- reconcile (source of truth) -----------------------------------------
|
|
1244
1266
|
|
|
1245
1267
|
async def reconcile(self) -> None:
|
|
@@ -2170,7 +2170,12 @@ class ServiceController:
|
|
|
2170
2170
|
|
|
2171
2171
|
policy = job.restart_policy or "always"
|
|
2172
2172
|
clean_exit = exit_code == 0
|
|
2173
|
-
|
|
2173
|
+
# A clean exit is a finished one-shot only for kind=service. A managed
|
|
2174
|
+
# database or model is a long-running server: exit 0 means something
|
|
2175
|
+
# stopped it (a host shutdown SIGTERMs Postgres, which exits 0), so it
|
|
2176
|
+
# restarts whatever its persisted 'on-failure' policy says.
|
|
2177
|
+
one_shot_done = clean_exit and job.kind is JobKind.service
|
|
2178
|
+
if policy == "no" or (policy == "on-failure" and one_shot_done):
|
|
2174
2179
|
final = JobStatus.completed if clean_exit else JobStatus.failed
|
|
2175
2180
|
error_class = (
|
|
2176
2181
|
None if clean_exit else _classify_service_exit(exit_code, oom_killed, gpu_oom)
|
|
@@ -74,8 +74,10 @@ def new_workload_row(
|
|
|
74
74
|
) -> Job:
|
|
75
75
|
"""Build the shared `building`/`running` Job skeleton for a create route.
|
|
76
76
|
|
|
77
|
-
`restart_policy` is the fixed `"on-failure"` literal
|
|
78
|
-
|
|
77
|
+
`restart_policy` is the fixed `"on-failure"` literal, not exposed as a
|
|
78
|
+
parameter. For these kinds `ServiceController._handle_crash` restarts on a
|
|
79
|
+
clean exit too (a host shutdown stops Postgres with exit 0), so a managed
|
|
80
|
+
server never settles to `completed`.
|
|
79
81
|
`submitted_by_token`/`idempotency_key` are read from `request` (the
|
|
80
82
|
same principal `authorize_create` already validated, and the same
|
|
81
83
|
`Idempotency-Key` header both routes read identically).
|
|
@@ -43,6 +43,7 @@ from nerdit.daemon.views.hosted import (
|
|
|
43
43
|
domain_cert_state,
|
|
44
44
|
domain_state,
|
|
45
45
|
load_hosted_context,
|
|
46
|
+
local_public_url,
|
|
46
47
|
)
|
|
47
48
|
from nerdit.daemon.views.service import _not_found, _resolve_service
|
|
48
49
|
from nerdit.db.models import JobKind, TokenRole
|
|
@@ -186,7 +187,7 @@ async def _context(request: Request, service_name: str) -> tuple[HostedContext,
|
|
|
186
187
|
endpoint = await queries.get_service_endpoint(service_name)
|
|
187
188
|
if endpoint is None:
|
|
188
189
|
return hosted, None
|
|
189
|
-
|
|
190
|
+
url = public_url_for(
|
|
190
191
|
endpoint.service_name,
|
|
191
192
|
endpoint.route,
|
|
192
193
|
mode=proxy.mode,
|
|
@@ -196,6 +197,7 @@ async def _context(request: Request, service_name: str) -> tuple[HostedContext,
|
|
|
196
197
|
https_port=proxy.https_port,
|
|
197
198
|
public_port=proxy.public_port,
|
|
198
199
|
)
|
|
200
|
+
return hosted, local_public_url(hosted, endpoint.service_name, url)
|
|
199
201
|
|
|
200
202
|
|
|
201
203
|
@router.get(
|
|
@@ -312,7 +314,6 @@ async def add_domain(
|
|
|
312
314
|
f"'{job.kind.value}' workloads cannot have a direct domain.",
|
|
313
315
|
hint="Only deployed apps (kind 'service') can be served under a domain.",
|
|
314
316
|
)
|
|
315
|
-
|
|
316
317
|
try:
|
|
317
318
|
validated = validate_domain(domain, reserved=_reserved(request))
|
|
318
319
|
# Accepted: from here the canonical (folded) name is the resource, and
|
|
@@ -378,6 +379,16 @@ async def add_domain(
|
|
|
378
379
|
# re-checks under the DB write lock). Nothing was written, so the honest
|
|
379
380
|
# answer is the 404 the resolve would have given a moment later.
|
|
380
381
|
raise _not_found(name)
|
|
382
|
+
if outcome == "hosted_only":
|
|
383
|
+
# Lot 5: a domain is a local route, and a locked app has none. Refused
|
|
384
|
+
# under the insert's own write lock, after the shape checks above, so
|
|
385
|
+
# a malformed name still gets its 422 and a lock cannot race in.
|
|
386
|
+
raise NerditError(
|
|
387
|
+
409,
|
|
388
|
+
"share.hosted_only_conflict",
|
|
389
|
+
f"Service '{service_name}' is hosted only: it has no local route.",
|
|
390
|
+
hint=f"Unlock it first: `nerdit share {service_name} --local-route`.",
|
|
391
|
+
)
|
|
381
392
|
if outcome == "taken":
|
|
382
393
|
# The message names the DOMAIN only. An owner-scoped principal must not
|
|
383
394
|
# be able to enumerate another owner's app names by probing names it
|
|
@@ -8,7 +8,7 @@ from fastapi import APIRouter, Request, Response
|
|
|
8
8
|
|
|
9
9
|
from nerdit.core.proxy import _route_id, public_url_for
|
|
10
10
|
from nerdit.daemon.errors import NerditError
|
|
11
|
-
from nerdit.daemon.views.hosted import load_hosted_context, public_urls_for
|
|
11
|
+
from nerdit.daemon.views.hosted import load_hosted_context, local_public_url, public_urls_for
|
|
12
12
|
from nerdit.db.models import ProxyStatusResponse, RouteItem, RouteListPage
|
|
13
13
|
from nerdit.utils.certs import ca_fingerprint
|
|
14
14
|
|
|
@@ -139,6 +139,7 @@ async def list_routes(
|
|
|
139
139
|
https_port=proxy_settings.https_port,
|
|
140
140
|
public_port=proxy_settings.public_port,
|
|
141
141
|
)
|
|
142
|
+
public_url = local_public_url(hosted, endpoint.service_name, public_url)
|
|
142
143
|
live: dict[str, object] | None = None
|
|
143
144
|
if live_table == "readable" and manager is not None:
|
|
144
145
|
# (P25, rev. 2 amendment 2) The id seam, NOT `build_route`: since
|
|
@@ -169,6 +170,7 @@ async def list_routes(
|
|
|
169
170
|
public_url=public_url,
|
|
170
171
|
public_urls=public_urls_for(hosted, endpoint.service_name, public_url),
|
|
171
172
|
live=live,
|
|
173
|
+
reason="hosted_only" if hosted.locked(endpoint.service_name) else None,
|
|
172
174
|
)
|
|
173
175
|
)
|
|
174
176
|
return RouteListPage(items=items, next_cursor=next_cursor, live_table=live_table)
|