From b616a9c51c3eb2deeaa6f241f362ed8989a507b1 Mon Sep 17 00:00:00 2001 From: Linus Fischer Date: Mon, 19 Oct 2026 22:18:49 +0200 Subject: [PATCH 01/17] feat!: rewrite the server on the LeiCraftMC full-stack Nuxt template (v2 foundation) NetIgnite v2, milestone 1: Nuxt 4 + Nuxt UI dashboard, Hono API at /api/v1 with OpenAPI docs, Drizzle on bun:sqlite, opaque bearer sessions and API keys. - Agent gateway at /ws/agent with protocol v2 (JSON frames, HELLO with capabilities, per-request answers, keep-alive). Agents enroll with a single-use token and generate their own secret; the server stores only its hash. - Devices with Wake-on-LAN, status checks (MAC link-local, IPv4, IPv6, SSH port, host agent), shutdown/reboot through a host agent, favorites. - Sharing devices with other users as viewer, operator or manager. - Public sign-up as an admin setting; admin settings page. - One-time import of NetIgnite v1 databases (scripts/import-v1.ts, bundled into the image). - Port 18232 kept from v1; the database moves to data/netignite.sqlite. - SQLite foreign keys enabled; transactions that need atomicity are synchronous. BREAKING CHANGE: v1 agents can't connect to v2 and have to be set up again. The REST API is replaced by /api/v1. --- .claude/settings.json | 50 + .gitattributes | 6 + .github/renovate.json | 3 + .github/workflows/ci.yml | 20 + .github/workflows/docker-publish.yml | 4 +- .gitignore | 39 +- .vscode/mcp.json | 12 + AGENTS.md | 54 + CLAUDE.md | 43 + LICENSE | 2 +- README.md | 294 +- app/api-client/client.gen.ts | 16 + app/api-client/client/client.gen.ts | 220 ++ app/api-client/client/index.ts | 26 + app/api-client/client/types.gen.ts | 191 ++ app/api-client/client/utils.gen.ts | 393 +++ app/api-client/core/auth.gen.ts | 48 + app/api-client/core/bodySerializer.gen.ts | 82 + app/api-client/core/params.gen.ts | 178 ++ app/api-client/core/pathSerializer.gen.ts | 171 ++ app/api-client/core/queryKeySerializer.gen.ts | 117 + app/api-client/core/serverSentEvents.gen.ts | 242 ++ app/api-client/core/types.gen.ts | 110 + app/api-client/core/utils.gen.ts | 140 + app/api-client/index.ts | 4 + app/api-client/sdk.gen.ts | 606 ++++ app/api-client/types.gen.ts | 2542 +++++++++++++++++ app/api-client/zod.gen.ts | 1244 ++++++++ app/app.config.ts | 13 + app.vue => app/app.vue | 8 +- app/assets/css/main.css | 55 + app/components/Gravatar.vue | 19 + .../dashboard/DashboardDeleteModal.vue | 78 + app/components/dashboard/DashboardModal.vue | 54 + .../dashboard/DashboardPageBody.vue | 5 + .../dashboard/DashboardPageHeader.vue | 50 + .../dashboard/DashboardSectionCard.vue | 69 + .../dashboard/DashboardStatCard.vue | 39 + app/components/dashboard/DataTable.vue | 457 +++ app/components/dashboard/UserMenu.vue | 111 + app/components/devices/PowerButtons.vue | 70 + app/components/devices/StatusBadge.vue | 21 + app/components/form/DateRangePicker.vue | 82 + app/components/img/AppIcon.vue | 7 + app/components/img/AppLogo.vue | 30 + app/components/layout/Footer.vue | 86 + app/components/layout/Header.vue | 58 + app/composables/stores/useOnboardingStore.ts | 59 + app/composables/stores/useUserStore.ts | 49 + app/composables/updateAPIClient.ts | 22 + app/composables/useAPI.ts | 218 ++ app/composables/useAppCookies.ts | 44 + app/composables/useAwaitedComputed.ts | 63 + app/composables/useDefaultOnFormError.ts | 15 + app/composables/useDeviceActions.ts | 82 + app/composables/useGravatarURL.ts | 15 + app/composables/usePageSeo.ts | 57 + app/composables/useRuntimeAppConfigs.ts | 14 + app/composables/useSubrouterInjectedData.ts | 87 + app/composables/useSubrouterPathDynamics.ts | 119 + app/error.vue | 19 + app/layouts/auth.vue | 20 + app/layouts/dashboard.vue | 136 + app/layouts/default.vue | 11 + app/layouts/onboarding.vue | 18 + app/middleware/auth.global.ts | 71 + app/middleware/rewrites.global.ts | 10 + app/pages/auth/forgot-password.vue | 99 + app/pages/auth/login.vue | 132 + app/pages/auth/reset-password.vue | 121 + app/pages/auth/signup.vue | 153 + app/pages/dashboard/admin/settings.vue | 76 + app/pages/dashboard/admin/users.vue | 318 +++ app/pages/dashboard/agents/[agent_id].vue | 101 + .../dashboard/agents/[agent_id]/index.vue | 365 +++ app/pages/dashboard/agents/index.vue | 109 + app/pages/dashboard/apikeys/[api_key_id].vue | 107 + .../dashboard/apikeys/[api_key_id]/index.vue | 267 ++ app/pages/dashboard/apikeys/index.vue | 151 + app/pages/dashboard/devices/[device_id].vue | 135 + .../dashboard/devices/[device_id]/index.vue | 355 +++ .../dashboard/devices/[device_id]/sharing.vue | 145 + app/pages/dashboard/devices/index.vue | 128 + app/pages/dashboard/index.vue | 157 + app/pages/dashboard/settings.vue | 47 + app/pages/dashboard/settings/index.vue | 185 ++ app/pages/dashboard/settings/security.vue | 223 ++ app/pages/welcome.vue | 122 + app/utils/abstractStore.ts | 107 + app/utils/format.ts | 33 + app/utils/netignite.ts | 88 + app/utils/roles.ts | 14 + app/utils/routeMatcher.ts | 69 + app/utils/types.ts | 26 + app/utils/url.ts | 12 + assets/css/forms.css | 33 - assets/css/global.css | 10 - biome.json | 79 + bun.lock | 2440 +++++++--------- bunfig.toml | 4 + components/DashboardPage.vue | 51 - components/Footer.vue | 47 - components/FormModal.vue | 75 - components/Sidebar.vue | 198 -- components/SimpleTable.vue | 34 - components/forms/FormDescription.vue | 16 - components/forms/FormGroup.vue | 6 - components/forms/FormInput.vue | 31 - components/forms/FormLabel.vue | 8 - components/forms/FormPWInput.vue | 56 - components/forms/FormSelect.vue | 34 - components/forms/FormSubmitBtn.vue | 8 - components/forms/FormTextarea.vue | 35 - components/img/icon.vue | 5 - components/img/logo-dark.vue | 31 - components/img/logo-white.vue | 31 - components/test-websocket.vue | 81 - composables/useAPI.ts | 120 - composables/useDataFilter.ts | 46 - composables/useNotificationToast.ts | 69 - config/config.sample.json | 1 - devutils/createAgent.ts | 17 - devutils/createTestUser.ts | 13 - docker/Dockerfile | 47 +- docker/docker-compose.yml | 23 +- docker/pterodactyl/Dockerfile | 13 - docker/pterodactyl/entrypoint.sh | 127 - drizzle/configs/drizzle.config.ts | 13 + drizzle/migrations/0000_purple_thanos.sql | 150 + drizzle/migrations/meta/0000_snapshot.json | 1065 +++++++ drizzle/migrations/meta/_journal.json | 13 + error.vue | 60 - example.env | 22 + layouts/auth.vue | 41 - layouts/dashboard.vue | 60 - layouts/default.vue | 40 - middleware/auth.ts | 28 - middleware/rewrites.global.ts | 9 - nuxt.config.ts | 115 +- openapi-ts.config.ts | 7 + package.json | 80 +- pages/account/settings.vue | 101 - pages/agents/[id]/index.vue | 278 -- pages/agents/index.vue | 214 -- pages/auth/login.vue | 131 - pages/auth/reset-password.vue | 16 - pages/devices/[id]/index.vue | 230 -- pages/devices/index.vue | 256 -- pages/index.vue | 206 -- plugins/suppress-router-warn.client.ts | 14 - public/robots.txt | 4 +- public/static/logo/icon.png | Bin 0 -> 10792 bytes public/static/logo/icon.svg | 3 + public/static/utils/sitemap.xml | 62 + scripts/api-client-generate.ts | 27 + scripts/compile/compileCMD.ts | 113 + scripts/compile/compiler.ts | 93 + scripts/compile/index.ts | 20 + scripts/db-utils.ts | 5 + scripts/entrypoint.ts | 10 + scripts/import-v1.ts | 75 + scripts/patch-api-client.ts | 19 + server/agent-control-service/agent.ts | 137 - .../agent-control-service/commands/message.ts | 137 - .../commands/registry.ts | 71 - server/agent-control-service/index.ts | 64 - server/agent-control-service/server.ts | 124 - server/api/account/[id]/index.put.ts | 73 - server/api/admin/users/index.post.ts | 37 - server/api/agent-control-service.ts | 5 - server/api/agents/[id]/index.delete.ts | 35 - server/api/agents/[id]/index.get.ts | 23 - server/api/agents/[id]/index.put.ts | 40 - .../api/agents/[id]/regenerate-secret.post.ts | 41 - server/api/agents/index.get.ts | 18 - server/api/agents/index.post.ts | 36 - server/api/agents/status.get.ts | 39 - server/api/auth/login.post.ts | 53 - server/api/auth/logout.post.ts | 15 - server/api/auth/session.get.ts | 19 - server/api/devices/[id]/index.delete.ts | 30 - server/api/devices/[id]/index.get.ts | 23 - server/api/devices/[id]/index.put.ts | 42 - server/api/devices/[id]/wakeup.post.ts | 113 - server/api/devices/index.get.ts | 24 - server/api/devices/index.post.ts | 31 - server/api/devices/status.get.ts | 47 - server/db/index.ts | 98 - server/db/models-test.ts | 112 - server/db/models/agents.ts | 133 - server/db/models/base.ts | 142 - server/db/models/devices.ts | 80 - server/db/models/password_resets.ts | 64 - server/db/models/sessions.ts | 45 - server/db/models/users.ts | 160 -- server/lib/agents/auth.ts | 154 + server/lib/agents/connection.ts | 180 ++ server/lib/agents/gateway.ts | 218 ++ server/lib/agents/protocol.ts | 117 + server/lib/agents/registry.ts | 79 + server/lib/api/index.ts | 139 + server/lib/api/utils/api-res.ts | 174 ++ server/lib/api/utils/apiVersionRouter.ts | 55 + server/lib/api/utils/authHandler.ts | 405 +++ server/lib/api/utils/email.ts | 142 + server/lib/api/utils/metadata.ts | 95 + server/lib/api/utils/preferences.ts | 114 + .../api/utils/shared-models/accountData.ts | 33 + .../utils/shared-models/api-helper-models.ts | 17 + .../api/utils/shared-models/netigniteData.ts | 54 + server/lib/api/utils/specHelpers.ts | 206 ++ server/lib/api/versions/v1/docs/index.ts | 18 + server/lib/api/versions/v1/index.ts | 156 + server/lib/api/versions/v1/middleware/auth.ts | 64 + .../api/versions/v1/middleware/requireUser.ts | 25 + .../v1/routes/account/apikeys/index.ts | 224 ++ .../v1/routes/account/apikeys/model.ts | 50 + .../api/versions/v1/routes/account/index.ts | 239 ++ .../api/versions/v1/routes/account/model.ts | 47 + .../v1/routes/account/preferences/index.ts | 89 + .../v1/routes/account/preferences/model.ts | 15 + .../lib/api/versions/v1/routes/admin/index.ts | 22 + .../v1/routes/admin/settings/index.ts | 46 + .../versions/v1/routes/admin/users/index.ts | 315 ++ .../versions/v1/routes/admin/users/model.ts | 78 + .../api/versions/v1/routes/agents/index.ts | 297 ++ .../api/versions/v1/routes/agents/model.ts | 65 + .../lib/api/versions/v1/routes/auth/index.ts | 325 +++ .../lib/api/versions/v1/routes/auth/model.ts | 48 + .../v1/routes/auth/reset-password/index.ts | 235 ++ .../v1/routes/auth/reset-password/model.ts | 18 + .../api/versions/v1/routes/devices/index.ts | 638 +++++ .../api/versions/v1/routes/devices/model.ts | 129 + server/lib/db/index.ts | 168 ++ server/lib/db/schema.ts | 260 ++ server/lib/db/utils.ts | 31 + server/lib/devices/actions.ts | 73 + server/lib/devices/permissions.ts | 94 + server/lib/devices/status.ts | 181 ++ server/lib/migration/v1Import.ts | 297 ++ server/lib/tasks/index.ts | 320 +++ server/lib/tasks/sampleTask.ts | 7 + server/lib/tasks/utils.ts | 28 + server/lib/utils/config.ts | 155 + server/lib/utils/constants.ts | 17 + server/lib/utils/cron.ts | 63 + server/lib/utils/crypto/cryptoKeys.ts | 54 + server/lib/utils/crypto/lcrypt.ts | 93 + server/lib/utils/crypto/objectCrypt.ts | 48 + server/lib/utils/crypto/signature.ts | 62 + server/lib/utils/index.ts | 81 + server/lib/utils/logger.ts | 63 + server/middleware/auth.ts | 14 - server/plugins/startup.ts | 165 +- server/routes/api/[...].ts | 44 + server/routes/ws/agent.ts | 5 + server/tsconfig.json | 19 - server/utils/auth/agentSecrets.ts | 35 - server/utils/auth/handler.ts | 40 - server/utils/auth/sessions.ts | 96 - server/utils/config.ts | 51 - server/utils/index.ts | 21 - server/utils/logger.ts | 59 - server/utils/validation.ts | 59 - shared/encoding.ts | 19 - shared/utils.ts | 34 - tests/agents.test.ts | 120 - tests/api-routes-v1.test.ts | 968 +++++++ tests/email.test.ts | 286 ++ tests/encoding.test.ts | 45 - tests/helpers/api.ts | 87 + tests/helpers/fake-agent.ts | 112 + tests/helpers/memory-transport.ts | 37 + tests/helpers/preload.ts | 112 + tests/helpers/seed.ts | 33 + tests/netignite.test.ts | 571 ++++ tests/v1-import.test.ts | 247 ++ tsconfig.json | 36 +- tsconfig/tsconfig.typecheck.json | 12 + utils/handlers/formModal.ts | 54 - utils/models/agent.ts | 152 - utils/models/device.ts | 220 -- utils/models/utils.ts | 63 - utils/simpleForm.ts | 53 - utils/userStore.ts | 16 - 285 files changed, 25963 insertions(+), 7965 deletions(-) create mode 100644 .claude/settings.json create mode 100644 .gitattributes create mode 100644 .github/renovate.json create mode 100644 .github/workflows/ci.yml create mode 100644 .vscode/mcp.json create mode 100644 AGENTS.md create mode 100644 CLAUDE.md create mode 100644 app/api-client/client.gen.ts create mode 100644 app/api-client/client/client.gen.ts create mode 100644 app/api-client/client/index.ts create mode 100644 app/api-client/client/types.gen.ts create mode 100644 app/api-client/client/utils.gen.ts create mode 100644 app/api-client/core/auth.gen.ts create mode 100644 app/api-client/core/bodySerializer.gen.ts create mode 100644 app/api-client/core/params.gen.ts create mode 100644 app/api-client/core/pathSerializer.gen.ts create mode 100644 app/api-client/core/queryKeySerializer.gen.ts create mode 100644 app/api-client/core/serverSentEvents.gen.ts create mode 100644 app/api-client/core/types.gen.ts create mode 100644 app/api-client/core/utils.gen.ts create mode 100644 app/api-client/index.ts create mode 100644 app/api-client/sdk.gen.ts create mode 100644 app/api-client/types.gen.ts create mode 100644 app/api-client/zod.gen.ts create mode 100644 app/app.config.ts rename app.vue => app/app.vue (56%) create mode 100644 app/assets/css/main.css create mode 100644 app/components/Gravatar.vue create mode 100644 app/components/dashboard/DashboardDeleteModal.vue create mode 100644 app/components/dashboard/DashboardModal.vue create mode 100644 app/components/dashboard/DashboardPageBody.vue create mode 100644 app/components/dashboard/DashboardPageHeader.vue create mode 100644 app/components/dashboard/DashboardSectionCard.vue create mode 100644 app/components/dashboard/DashboardStatCard.vue create mode 100644 app/components/dashboard/DataTable.vue create mode 100644 app/components/dashboard/UserMenu.vue create mode 100644 app/components/devices/PowerButtons.vue create mode 100644 app/components/devices/StatusBadge.vue create mode 100644 app/components/form/DateRangePicker.vue create mode 100644 app/components/img/AppIcon.vue create mode 100644 app/components/img/AppLogo.vue create mode 100644 app/components/layout/Footer.vue create mode 100644 app/components/layout/Header.vue create mode 100644 app/composables/stores/useOnboardingStore.ts create mode 100644 app/composables/stores/useUserStore.ts create mode 100644 app/composables/updateAPIClient.ts create mode 100644 app/composables/useAPI.ts create mode 100644 app/composables/useAppCookies.ts create mode 100644 app/composables/useAwaitedComputed.ts create mode 100644 app/composables/useDefaultOnFormError.ts create mode 100644 app/composables/useDeviceActions.ts create mode 100644 app/composables/useGravatarURL.ts create mode 100644 app/composables/usePageSeo.ts create mode 100644 app/composables/useRuntimeAppConfigs.ts create mode 100644 app/composables/useSubrouterInjectedData.ts create mode 100644 app/composables/useSubrouterPathDynamics.ts create mode 100644 app/error.vue create mode 100644 app/layouts/auth.vue create mode 100644 app/layouts/dashboard.vue create mode 100644 app/layouts/default.vue create mode 100644 app/layouts/onboarding.vue create mode 100644 app/middleware/auth.global.ts create mode 100644 app/middleware/rewrites.global.ts create mode 100644 app/pages/auth/forgot-password.vue create mode 100644 app/pages/auth/login.vue create mode 100644 app/pages/auth/reset-password.vue create mode 100644 app/pages/auth/signup.vue create mode 100644 app/pages/dashboard/admin/settings.vue create mode 100644 app/pages/dashboard/admin/users.vue create mode 100644 app/pages/dashboard/agents/[agent_id].vue create mode 100644 app/pages/dashboard/agents/[agent_id]/index.vue create mode 100644 app/pages/dashboard/agents/index.vue create mode 100644 app/pages/dashboard/apikeys/[api_key_id].vue create mode 100644 app/pages/dashboard/apikeys/[api_key_id]/index.vue create mode 100644 app/pages/dashboard/apikeys/index.vue create mode 100644 app/pages/dashboard/devices/[device_id].vue create mode 100644 app/pages/dashboard/devices/[device_id]/index.vue create mode 100644 app/pages/dashboard/devices/[device_id]/sharing.vue create mode 100644 app/pages/dashboard/devices/index.vue create mode 100644 app/pages/dashboard/index.vue create mode 100644 app/pages/dashboard/settings.vue create mode 100644 app/pages/dashboard/settings/index.vue create mode 100644 app/pages/dashboard/settings/security.vue create mode 100644 app/pages/welcome.vue create mode 100644 app/utils/abstractStore.ts create mode 100644 app/utils/format.ts create mode 100644 app/utils/netignite.ts create mode 100644 app/utils/roles.ts create mode 100644 app/utils/routeMatcher.ts create mode 100644 app/utils/types.ts create mode 100644 app/utils/url.ts delete mode 100644 assets/css/forms.css delete mode 100644 assets/css/global.css create mode 100644 biome.json create mode 100644 bunfig.toml delete mode 100644 components/DashboardPage.vue delete mode 100644 components/Footer.vue delete mode 100644 components/FormModal.vue delete mode 100644 components/Sidebar.vue delete mode 100644 components/SimpleTable.vue delete mode 100644 components/forms/FormDescription.vue delete mode 100644 components/forms/FormGroup.vue delete mode 100644 components/forms/FormInput.vue delete mode 100644 components/forms/FormLabel.vue delete mode 100644 components/forms/FormPWInput.vue delete mode 100644 components/forms/FormSelect.vue delete mode 100644 components/forms/FormSubmitBtn.vue delete mode 100644 components/forms/FormTextarea.vue delete mode 100644 components/img/icon.vue delete mode 100644 components/img/logo-dark.vue delete mode 100644 components/img/logo-white.vue delete mode 100644 components/test-websocket.vue delete mode 100644 composables/useAPI.ts delete mode 100644 composables/useDataFilter.ts delete mode 100644 composables/useNotificationToast.ts delete mode 100644 config/config.sample.json delete mode 100644 devutils/createAgent.ts delete mode 100644 devutils/createTestUser.ts delete mode 100644 docker/pterodactyl/Dockerfile delete mode 100644 docker/pterodactyl/entrypoint.sh create mode 100644 drizzle/configs/drizzle.config.ts create mode 100644 drizzle/migrations/0000_purple_thanos.sql create mode 100644 drizzle/migrations/meta/0000_snapshot.json create mode 100644 drizzle/migrations/meta/_journal.json delete mode 100644 error.vue create mode 100644 example.env delete mode 100644 layouts/auth.vue delete mode 100644 layouts/dashboard.vue delete mode 100644 layouts/default.vue delete mode 100644 middleware/auth.ts delete mode 100644 middleware/rewrites.global.ts create mode 100644 openapi-ts.config.ts delete mode 100644 pages/account/settings.vue delete mode 100644 pages/agents/[id]/index.vue delete mode 100644 pages/agents/index.vue delete mode 100644 pages/auth/login.vue delete mode 100644 pages/auth/reset-password.vue delete mode 100644 pages/devices/[id]/index.vue delete mode 100644 pages/devices/index.vue delete mode 100644 pages/index.vue delete mode 100644 plugins/suppress-router-warn.client.ts create mode 100644 public/static/logo/icon.png create mode 100644 public/static/logo/icon.svg create mode 100644 public/static/utils/sitemap.xml create mode 100644 scripts/api-client-generate.ts create mode 100644 scripts/compile/compileCMD.ts create mode 100644 scripts/compile/compiler.ts create mode 100644 scripts/compile/index.ts create mode 100644 scripts/db-utils.ts create mode 100644 scripts/entrypoint.ts create mode 100644 scripts/import-v1.ts create mode 100644 scripts/patch-api-client.ts delete mode 100644 server/agent-control-service/agent.ts delete mode 100644 server/agent-control-service/commands/message.ts delete mode 100644 server/agent-control-service/commands/registry.ts delete mode 100644 server/agent-control-service/index.ts delete mode 100644 server/agent-control-service/server.ts delete mode 100644 server/api/account/[id]/index.put.ts delete mode 100644 server/api/admin/users/index.post.ts delete mode 100644 server/api/agent-control-service.ts delete mode 100644 server/api/agents/[id]/index.delete.ts delete mode 100644 server/api/agents/[id]/index.get.ts delete mode 100644 server/api/agents/[id]/index.put.ts delete mode 100644 server/api/agents/[id]/regenerate-secret.post.ts delete mode 100644 server/api/agents/index.get.ts delete mode 100644 server/api/agents/index.post.ts delete mode 100644 server/api/agents/status.get.ts delete mode 100644 server/api/auth/login.post.ts delete mode 100644 server/api/auth/logout.post.ts delete mode 100644 server/api/auth/session.get.ts delete mode 100644 server/api/devices/[id]/index.delete.ts delete mode 100644 server/api/devices/[id]/index.get.ts delete mode 100644 server/api/devices/[id]/index.put.ts delete mode 100644 server/api/devices/[id]/wakeup.post.ts delete mode 100644 server/api/devices/index.get.ts delete mode 100644 server/api/devices/index.post.ts delete mode 100644 server/api/devices/status.get.ts delete mode 100644 server/db/index.ts delete mode 100644 server/db/models-test.ts delete mode 100644 server/db/models/agents.ts delete mode 100644 server/db/models/base.ts delete mode 100644 server/db/models/devices.ts delete mode 100644 server/db/models/password_resets.ts delete mode 100644 server/db/models/sessions.ts delete mode 100644 server/db/models/users.ts create mode 100644 server/lib/agents/auth.ts create mode 100644 server/lib/agents/connection.ts create mode 100644 server/lib/agents/gateway.ts create mode 100644 server/lib/agents/protocol.ts create mode 100644 server/lib/agents/registry.ts create mode 100644 server/lib/api/index.ts create mode 100644 server/lib/api/utils/api-res.ts create mode 100644 server/lib/api/utils/apiVersionRouter.ts create mode 100644 server/lib/api/utils/authHandler.ts create mode 100644 server/lib/api/utils/email.ts create mode 100644 server/lib/api/utils/metadata.ts create mode 100644 server/lib/api/utils/preferences.ts create mode 100644 server/lib/api/utils/shared-models/accountData.ts create mode 100644 server/lib/api/utils/shared-models/api-helper-models.ts create mode 100644 server/lib/api/utils/shared-models/netigniteData.ts create mode 100644 server/lib/api/utils/specHelpers.ts create mode 100644 server/lib/api/versions/v1/docs/index.ts create mode 100644 server/lib/api/versions/v1/index.ts create mode 100644 server/lib/api/versions/v1/middleware/auth.ts create mode 100644 server/lib/api/versions/v1/middleware/requireUser.ts create mode 100644 server/lib/api/versions/v1/routes/account/apikeys/index.ts create mode 100644 server/lib/api/versions/v1/routes/account/apikeys/model.ts create mode 100644 server/lib/api/versions/v1/routes/account/index.ts create mode 100644 server/lib/api/versions/v1/routes/account/model.ts create mode 100644 server/lib/api/versions/v1/routes/account/preferences/index.ts create mode 100644 server/lib/api/versions/v1/routes/account/preferences/model.ts create mode 100644 server/lib/api/versions/v1/routes/admin/index.ts create mode 100644 server/lib/api/versions/v1/routes/admin/settings/index.ts create mode 100644 server/lib/api/versions/v1/routes/admin/users/index.ts create mode 100644 server/lib/api/versions/v1/routes/admin/users/model.ts create mode 100644 server/lib/api/versions/v1/routes/agents/index.ts create mode 100644 server/lib/api/versions/v1/routes/agents/model.ts create mode 100644 server/lib/api/versions/v1/routes/auth/index.ts create mode 100644 server/lib/api/versions/v1/routes/auth/model.ts create mode 100644 server/lib/api/versions/v1/routes/auth/reset-password/index.ts create mode 100644 server/lib/api/versions/v1/routes/auth/reset-password/model.ts create mode 100644 server/lib/api/versions/v1/routes/devices/index.ts create mode 100644 server/lib/api/versions/v1/routes/devices/model.ts create mode 100644 server/lib/db/index.ts create mode 100644 server/lib/db/schema.ts create mode 100644 server/lib/db/utils.ts create mode 100644 server/lib/devices/actions.ts create mode 100644 server/lib/devices/permissions.ts create mode 100644 server/lib/devices/status.ts create mode 100644 server/lib/migration/v1Import.ts create mode 100644 server/lib/tasks/index.ts create mode 100644 server/lib/tasks/sampleTask.ts create mode 100644 server/lib/tasks/utils.ts create mode 100644 server/lib/utils/config.ts create mode 100644 server/lib/utils/constants.ts create mode 100644 server/lib/utils/cron.ts create mode 100644 server/lib/utils/crypto/cryptoKeys.ts create mode 100644 server/lib/utils/crypto/lcrypt.ts create mode 100644 server/lib/utils/crypto/objectCrypt.ts create mode 100644 server/lib/utils/crypto/signature.ts create mode 100644 server/lib/utils/index.ts create mode 100644 server/lib/utils/logger.ts delete mode 100644 server/middleware/auth.ts create mode 100644 server/routes/api/[...].ts create mode 100644 server/routes/ws/agent.ts delete mode 100644 server/tsconfig.json delete mode 100644 server/utils/auth/agentSecrets.ts delete mode 100644 server/utils/auth/handler.ts delete mode 100644 server/utils/auth/sessions.ts delete mode 100644 server/utils/config.ts delete mode 100644 server/utils/index.ts delete mode 100644 server/utils/logger.ts delete mode 100644 server/utils/validation.ts delete mode 100644 shared/encoding.ts delete mode 100644 shared/utils.ts delete mode 100644 tests/agents.test.ts create mode 100644 tests/api-routes-v1.test.ts create mode 100644 tests/email.test.ts delete mode 100644 tests/encoding.test.ts create mode 100644 tests/helpers/api.ts create mode 100644 tests/helpers/fake-agent.ts create mode 100644 tests/helpers/memory-transport.ts create mode 100644 tests/helpers/preload.ts create mode 100644 tests/helpers/seed.ts create mode 100644 tests/netignite.test.ts create mode 100644 tests/v1-import.test.ts create mode 100644 tsconfig/tsconfig.typecheck.json delete mode 100644 utils/handlers/formModal.ts delete mode 100644 utils/models/agent.ts delete mode 100644 utils/models/device.ts delete mode 100644 utils/models/utils.ts delete mode 100644 utils/simpleForm.ts delete mode 100644 utils/userStore.ts diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..b94b192 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,50 @@ +{ + "mcpServers": { + "nuxt": { + "type": "url", + "url": "https://nuxt.com/mcp" + }, + "nuxt-ui": { + "type": "url", + "url": "https://ui.nuxt.com/mcp" + } + }, + "commands": { + "api-client": { + "description": "Regenerate the typed API client", + "prompt": "Regenerate and verify the generated API client for this full-stack Nuxt project.\n\n1. Run `bun run api-client:generate` (scripts/api-client-generate.ts boots the API in-process, reads its OpenAPI spec, and patches the generated files — no dev server needed).\n2. Do not hand-edit generated `*.gen.ts` files under `app/api-client/`.\n3. If generation fails, diagnose whether the Hono backend or the OpenAPI route is the issue.\n4. Summarize the outcome and any follow-up needed." + }, + "db": { + "description": "Run Drizzle migrations", + "prompt": "Run the Drizzle migration flow for this project.\n\n1. Run `bun run db:generate` to generate migrations from `server/lib/db/schema.ts` into `drizzle/migrations/`.\n2. Run `bun run db:migrate` to apply them (the app also auto-migrates on startup when `NETIGNITE_DB_AUTO_MIGRATE` is true — the default).\n3. Summarize what was generated or applied." + }, + "verify": { + "description": "Run the repo verification flow", + "prompt": "Run the standard verification flow for this Nuxt 4 + Bun project.\n\n1. Run `bun run typecheck` (runs `nuxt typecheck` then `tsc -p ./tsconfig/tsconfig.typecheck.json`).\n2. Run `bun test`.\n3. Summarize any failures or warnings.\n4. If this command was triggered after a code change, fix issues that are clearly caused by that change before summarizing." + }, + "test": { + "description": "Run the test suite", + "prompt": "Run the test suite for this Nuxt 4 + Bun project.\n\n1. Run `bun test`.\n2. If tests fail, diagnose and fix the root cause.\n3. Summarize pass/fail status and any fixes applied." + }, + "typecheck": { + "description": "Run the TypeScript type checker", + "prompt": "Run the full typecheck flow for this Nuxt 4 + Bun project.\n\n1. Run `bun run typecheck` which runs `nuxt typecheck` then `tsc -p ./tsconfig/tsconfig.typecheck.json`.\n2. If there are type errors, diagnose and fix them before summarizing.\n3. Report the pass/fail status and what was fixed, if anything." + }, + "dev": { + "description": "Start or inspect the dev setup", + "prompt": "Work on the local development setup for this project.\n\n1. If needed, install dependencies with `bun install`.\n2. Use `bun run dev` for the dev server on port 18232.\n3. If there is a dev-server issue, inspect the Nuxt config, runtime env, and Bun-specific wiring before making changes.\n4. Summarize what you started, changed, or found." + } + }, + "fileScan": { + "exclude": [ + ".git/**", + "node_modules/**", + ".nuxt/**", + ".output/**", + ".nitro/**", + ".data/**", + ".cache/**", + "dist/**" + ] + } +} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..7df4379 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,6 @@ +# LF everywhere (Biome formats with LF; keeps Windows checkouts clean with core.autocrlf). +* text=auto eol=lf + +*.png binary +*.ico binary +*.woff2 binary diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 0000000..344c613 --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,3 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json" +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..bcf774e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,20 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + - run: bun install --frozen-lockfile + - run: bun run check:ci + - run: bun run typecheck + - run: bun test \ No newline at end of file diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 60d5706..078aa9b 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -50,8 +50,8 @@ jobs: shell: bash run: bun install - #- name: Build Nuxt application - # run: bun run build + - name: Build Nuxt application + run: bun run build - name: Setup Docker id: docker-setup diff --git a/.gitignore b/.gitignore index 194dd79..7c359a8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,29 +1,52 @@ -# Nuxt dev/build outputs +# Node +node_modules + +# Dev / Build / compile output .output .data .nuxt .nitro .cache -dist +build/ +out/ +dist/ +*.tgz -# Node dependencies -node_modules +# Drizzle artifacts +.drizzle + +# TypeScript +*.tsbuildinfo + +# Coverage and test reports +coverage +*.lcov +junit.xml # Logs logs *.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* -# Misc +# Editor / OS .DS_Store .fleet .idea -# Local env files +# Environment .env .env.* !.env.example +#Tests +tmp-data-* + +# Backend data & config (keep examples) +data/ +!app/data/ config/* -!config/*sample* +!config/*.example.json -data/ \ No newline at end of file +.claude/settings.local.json \ No newline at end of file diff --git a/.vscode/mcp.json b/.vscode/mcp.json new file mode 100644 index 0000000..f36ea74 --- /dev/null +++ b/.vscode/mcp.json @@ -0,0 +1,12 @@ +{ + "servers": { + "nuxt": { + "type": "http", + "url": "https://nuxt.com/mcp" + }, + "nuxt-ui": { + "type": "http", + "url": "https://ui.nuxt.com/mcp" + } + } +} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..a8d29d5 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,54 @@ +# AGENTS.md — operating manual for AI coding agents + +You are working in the NetIgnite server: a LeiCraftMC full-stack Nuxt app (Nuxt frontend + Hono +backend in `server/`) plus the WebSocket gateway that NetIgnite agents connect to. +Follow the LeiCraftMC Style Guides: https://github.com/LeiCraftMC/Style-Guides. + +## Must read + +- [docs/00-overview.md](https://github.com/LeiCraftMC/Style-Guides/blob/main/docs/00-overview.md) +- [docs/01-project-structure.md](https://github.com/LeiCraftMC/Style-Guides/blob/main/docs/01-project-structure.md) — the full-stack Nuxt shape +- [docs/04-backend-hono.md](https://github.com/LeiCraftMC/Style-Guides/blob/main/docs/04-backend-hono.md) — Mounting Hono in Nitro +- [docs/05-api-contract.md](https://github.com/LeiCraftMC/Style-Guides/blob/main/docs/05-api-contract.md) +- [docs/06-frontend-nuxt.md](https://github.com/LeiCraftMC/Style-Guides/blob/main/docs/06-frontend-nuxt.md) +- [docs/07-state-and-data.md](https://github.com/LeiCraftMC/Style-Guides/blob/main/docs/07-state-and-data.md) + +## Non-negotiable + +- Nuxt 4 `app/` srcDir; Tailwind v4 CSS-first; no `tailwind.config.js`. Dark-only (no toggle). +- The Hono backend lives in `server/` and owns `/api` — no `Bun.serve`, no `Main.main()`; init in + `server/plugins/startup.ts`. +- Every API response uses the `{ success, code, message, data }` envelope via `APIResponse.*` + (errors omit `data`). +- Validate with `hono-openapi`'s validator (`import { validator as zValidator } from "hono-openapi"`); routes in `server/lib/api/versions/v/routes//{index.ts, model.ts}`. +- Auth uses opaque bearer tokens (`__:`, `Bun.password`-hashed) — not JWT. + See docs/10-auth.md. +- Frontend API access only through `useAPI`; global state via `AbstractStore` over `useState`; + component-local form/UI state with `reactive()`/`ref()` is fine. +- Lucide icons only (`i-lucide-*`). Never hand-edit `*.gen.ts` under `app/api-client/` — + regenerate with `bun run api-client:generate`. +- `nitro.rollupConfig.external: ["bun:sqlite"]` in `nuxt.config.ts`. WebSocket routes + (`server/routes/ws/`) require `nitro.experimental.websocket = true` (Bun preset). +- Format with Biome before finishing. Conventional Commits. + +## NetIgnite specifics + +- **Port 18232** in dev and prod — a deliberate exception to the style guide's 12xxx rule, kept from + v1 so existing compose files, proxies and agents keep working. +- **Agents** connect to `/ws/agent` (`server/routes/ws/agent.ts` → `server/lib/agents/`). The + protocol is documented in `server/lib/agents/protocol.ts`; commands are only sent if the agent's + HELLO listed the capability. Agent credentials are `netignite_agent_:`; the + secret is generated by the agent at enrollment (`server/lib/agents/auth.ts`) and never shown. +- **Devices** are owned by one user and shared per device with a role (viewer/operator/manager). + Check access only through `DevicePermissions` (`server/lib/devices/permissions.ts`). Agents are + never shared. +- Device status is polled server-side (`DeviceStatusService`) and cached; routes read the cache. +- **Transactions:** drizzle's bun-sqlite `transaction()` is synchronous and commits at the first + `await` inside its callback. Do async work (password hashing) first and keep transaction + callbacks synchronous (`.run()`, `.get()`, `.all()`) when atomicity matters. +- SQLite foreign keys are enabled in `DB.init` (`PRAGMA foreign_keys = ON`); `onDelete` rules rely + on it. +- `scripts/import-v1.ts` imports a NetIgnite v1 database (bundled into `.output/import-v1.mjs` by + `bun run build`). +- Tests: `tests/netignite.test.ts` (API + gateway with `tests/helpers/fake-agent.ts`) and + `tests/v1-import.test.ts`. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..35e3425 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,43 @@ +# CLAUDE.md — Claude Code specifics + +Read `AGENTS.md` first. This file adds Claude-Code-specific notes. + +## Slash commands + +Defined in `.claude/settings.json`: + +- `/api-client` — regenerate the typed API client (boots the API in-process; no dev server needed). +- `/db` — run Drizzle migrations. +- `/verify` — typecheck + tests. +- `/typecheck` — `bun run typecheck` (`nuxt typecheck` + `tsc`, includes `server/`). +- `/test` — `bun test`. +- `/dev` — start/inspect the dev setup. + +## MCP servers + +`mcpServers` in `.claude/settings.json` and `.vscode/mcp.json` both register `nuxt` and `nuxt-ui`. + +## Backend in `server/` + +This is the full-stack shape: Hono lives in `server/lib/api`, mounted at `/api` by +`server/routes/api/[...].ts`, and initialized by `server/plugins/startup.ts`. After changing a +backend route, regenerate the client with `bun run api-client:generate`. Never hand-edit +`app/api-client/*.gen.ts`. + +## Frontend conventions + +- Route map and access rules: see the header of `app/middleware/auth.global.ts` and the Frontend + section of `README.md`. The template is deliberately rich; delete unused parts instead of + working around them. +- Reference components by their Nuxt auto-import names (`LayoutHeader`, `ImgAppLogo`, + `DashboardDataTable`, `FormDateRangePicker`, …). Don't add explicit imports that only the + `