Skip to content

refactor(dashboard): align server conventions with wolfstar.rocks - #48

Merged
kodiakhq[bot] merged 10 commits into
mainfrom
t3code/align-dashboard-server
Aug 18, 2026
Merged

refactor(dashboard): align server conventions with wolfstar.rocks#48
kodiakhq[bot] merged 10 commits into
mainfrom
t3code/align-dashboard-server

Conversation

@RedStar071

@RedStar071 RedStar071 commented Aug 18, 2026

Copy link
Copy Markdown
Member

Summary

Aligns apps/dashboard/server/ with the Nitro server conventions used by
wolfstar-project/wolfstar.rocks, and installs the
nitro and nuxt Agent Skills that server-side work on this app was missing.

  • Each route file exports its handler directly as the module default (export default defineEventHandler(...))
    instead of binding it to a const first.
  • New server/utils/errors.ts — a catalogue of the transport-level failures routes return
    (errors.notFound(), errors.misconfigured(variable)), mirroring wolfstar.rocks' own server/utils/errors.ts.
    Statuses and bodies are unchanged; successful dispositions still serialise through json(...).
  • server/utils/auth-environment.ts becomes server/utils/environment.ts and gains the webhook's
    GITHUB_WEBHOOK_SECRET and AGENT_ZERO_CHECKOUT_PATH resolvers, so every environment read the server does
    lives in one module.
  • Skills: nitro from antfu/skills (the source already used for tsdown and turborepo) and nuxt from
    onmax/nuxt-skills (the source of the existing nuxt-content, nuxt-i18n, nuxt-modules, nuxt-seo).

No observable HTTP behavior changes: same paths, same statuses, same response bodies.

Why

server/ had the same disposition spelled out inline in several places — a 404 literal in both transports,
two 503 literals in the webhook route — and read process.env directly at one call site while a neighbouring
util already existed for another variable. Naming the failure and centralising the reads keeps the two
transports from drifting apart and makes the fail-closed paths testable.

Boundary is unchanged and stays where the orpc-server skill puts it: server/ remains the transport
adapter and composition root, packages/api keeps the router, and nothing new reaches the runtime.

Two wolfstar.rocks conventions are deliberately not adopted, because this repository decides them
differently and the reasons are recorded in .skills/orpc-server/SKILL.md:

  • Nitro auto-imports and #server/* aliasesserver/** and app/** keep explicit imports so every
    symbol's origin stays visible at the call site.
  • useRuntimeConfig in place of process.envruntimeConfig defaults are baked at build time and
    would force every variable into a NUXT_-prefixed name, while a deployment sets GITHUB_WEBHOOK_SECRET
    and AGENT_ZERO_CHECKOUT_PATH at run time. The resolvers stay lazy, and take the environment record as an
    argument so tests never mutate the real process environment.

Formatting (tabs, double quotes) is also not copied: tooling/oxc/.oxfmtrc.json governs the whole monorepo.

Verification

Run on this branch, rebased onto origin/main (be40c80):

  • aube run check:repoRepository metadata valid; 8 Agent Skills available.
  • aube run lint:ci — 25/25 tasks, Found 0 warnings and 0 errors, knip clean
  • aube run typecheck — 25/25 tasks, no errors
  • aube test — 25/25 tasks (dashboard: 10 files, 49 tests)
  • aube run build — 16/16 tasks

Additionally, apps/dashboard/.output was inspected after nuxt build: /rpc/**, /api/v1/**,
/api/dashboard, and /webhooks/github are all present, so nothing was dropped by moving the handler
exports.

New deterministic tests: apps/dashboard/test/unit/errors.test.ts (both catalogue entries, status and body)
and four cases added to apps/dashboard/test/unit/environment.test.ts for the fail-closed webhook resolvers
(absent and blank values).

Safety and compatibility

  • I added or updated deterministic tests for changed behavior.
  • I preserved observe mode as read-only, or explained the policy change above.
  • Runtime commands and target-repository writes remain inside the runner boundary.
  • I did not expose secrets, tokens, personal data, or untrusted output in logs.
  • I updated documentation and Agent Skills when workflows or boundaries changed.

The webhook route still fails closed on either missing variable, with the byte-identical 503 body it returned
before. errors.misconfigured names the variable only — never a value — and the 500 path still redacts
through redactSecrets.

Reviewer notes

  • apps/dashboard/server/utils/auth-environment.tsenvironment.ts is a rename plus two added resolvers;
    its test file was renamed to match. dashboardUrlFromEnvironment is unchanged.
  • .skills/orpc-server/SKILL.md gains three rules (direct default export, error catalogue, environment
    module) so the next change to server/ follows the same shape.
  • The skills commit is separate from the refactor and touches no application code.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Note

Align dashboard server error handling and environment utilities with wolfstar.rocks conventions

  • Introduces a centralized errors catalog (errors.ts) with factory functions for notFound (404), misconfigured (503), and internal (500, with secret redaction), replacing custom errorResponse/json helpers across server routes.
  • Adds typed environment resolvers in environment.ts for NUXT_PUBLIC_SITE_URL, GITHUB_WEBHOOK_SECRET, and AGENT_ZERO_CHECKOUT_PATH, replacing ad-hoc runtimeConfig access.
  • Updates the GitHub webhook handler, RPC catch-all, and /api/v1 catch-all to use the new errors catalog and environment resolvers, and inlines handler exports to match the wolfstar.rocks convention.
  • Adds the GitHub webhook path item to the OpenAPI spec under webhooks instead of paths.
  • Behavioral Change: unmatched RPC and /api/v1 routes now throw H3 404 errors instead of returning custom JSON bodies; unexpected errors surface as H3 500s with redacted messages instead of custom error responses.

Macroscope summarized 8d2eba8.

Install the `nitro` skill from antfu/skills (the source this repo already
uses for `tsdown` and `turborepo`) and the `nuxt` skill from
onmax/nuxt-skills (the source of the existing `nuxt-content`, `nuxt-i18n`,
`nuxt-modules`, and `nuxt-seo` skills), so server-side work on
`apps/dashboard` has the framework references it currently lacks.

`skilld add --agent codex` writes only `.agents/skills/`, so the
`.claude/skills/` symlinks are added alongside, matching every other
installed skill.
Adopt the Nitro server conventions wolfstar.rocks uses, minus the ones this
repository's own rules already decide differently (Nitro auto-imports and
`#server/*` aliases stay out: `server/**` and `app/**` keep explicit imports
so every symbol's origin is visible at the call site).

- Export each route handler directly as the module default rather than
  binding it to a `const` first, so the one shape Nitro scans for is the
  one the file declares.
- Add `server/utils/errors.ts`, a catalogue of the transport-level failures
  routes return (`notFound`, `misconfigured`), so a disposition cannot drift
  into two shapes across the RPC and OpenAPI transports. Bodies and statuses
  are unchanged; successful dispositions still serialise through `json`.
- Rename `server/utils/auth-environment.ts` to `server/utils/environment.ts`
  and move the webhook's `GITHUB_WEBHOOK_SECRET` and
  `AGENT_ZERO_CHECKOUT_PATH` reads into it, one resolver each, taking the
  environment record as an argument. They deliberately stay off Nuxt's
  `runtimeConfig`, whose defaults are baked at build time and would force
  every variable into a `NUXT_`-prefixed name a deployment does not set.

Safety: the webhook still fails closed on either missing variable, with the
same 503 body, and neither resolver reports a value — only the variable's
name. Covered by unit tests for the fail-closed paths and the error
catalogue.

Verified with `aube run test --filter @agent-zero/dashboard` (49 passing),
`lint`, `knip`, `nuxt build` (all four routes present in `.output`), and
`typecheck` (no errors under `server/` or `test/`).
@vercel

vercel Bot commented Aug 18, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agent-zero-dashboard Error Error Aug 18, 2026 8:04pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
agent-zero-docs Skipped Skipped Aug 18, 2026 8:04pm

Comment thread apps/dashboard/server/utils/environment.ts Outdated
@macroscopeapp

macroscopeapp Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 8d2eba8

Macroscope's review found this PR approvable — Mechanical refactor aligning server conventions: centralizes error handling into a standardized errors utility, consolidates environment resolvers, and switches to Nitro auto-imports. Functional behavior is preserved with comprehensive test coverage for new utilities.

Notes:

  • No code objects were reviewed. Approvability was decided on eligibility alone.

You can add or adjust custom eligibility rules. Learn more.

Co-authored-by: macroscopeapp[bot] <170038800+macroscopeapp[bot]@users.noreply.github.com>
Signed-off-by: RedStar <redstar071@proton.me>
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Aug 18, 2026
Follow wolfstar.rocks' server layer the rest of the way, and Nuxt's own
guidance with it: routes stop importing what Nitro already provides and
stop building `Response` objects by hand.

- Remove `server/utils/respond.ts`. Its `json`/`errorResponse` helpers
  duplicated what Nitro does for a returned object and a thrown `H3Error`.
- `server/utils/errors.ts` now returns `H3Error`s built with `createError`,
  including `errors.internal(error)` for the unexpected case. Routes throw
  them, and Nitro serialises and logs the result — the same envelope the
  app's own `resolveErrorStatus` already reads on the client side.
- Route files rely on Nitro's auto-imports for h3 helpers and for this app's
  `server/utils/**` exports. Only workspace and third-party packages are
  imported explicitly, plus `createError` inside `errors.ts`, which the
  plain-Node unit suite loads directly.
- The webhook returns plain objects, with `setResponseStatus(event, 400)`
  for a rejected delivery, instead of serialising each disposition itself.

Safety: `errors.internal` still redacts through `redactSecrets`, and now
deliberately attaches no `cause`, since Nitro logs a thrown error whole and
the original message is the value most likely to carry a token. The webhook
still fails closed on a missing secret or checkout path, with the same
message. Covered by unit tests, including a redaction case that asserts the
credential appears nowhere on the thrown error.

Verified with `check:repo`, `lint:ci`, `typecheck`, `test` (25/25 tasks,
dashboard 51 tests), and `build` (16/16). A `nuxt dev` smoke run confirms
the wire behavior: `POST /webhooks/github` without a secret answers 503
`GITHUB_WEBHOOK_SECRET is not configured`, `/rpc/does/not/exist` and
`/api/v1/nope` answer 404 `Not found`, and `/api/v1/health` still answers
200 with the health payload.
The review feedback that dropped `.trim()` from
`githubWebhookSecretFromEnvironment` left its unit tests asserting the old
behavior, so the suite was red. GitHub signs each delivery with the exact
bytes configured on the hook, so the resolver must not alter them; only an
absent or empty variable counts as unconfigured. Record that reason on the
resolver and assert it instead.
Comment thread apps/dashboard/server/utils/errors.ts
- Webhook documented as OpenAPI 3.1 webhook, not a routed path
- Clarify why plain Nitro handler avoids body parsing
- Ensure error messages reach client via Nitro's error handler
- Add tests for webhook spec integration and error message preservation
The prior commit annotated `githubWebhookPathItem` as
`NonNullable<OpenAPIDocument['webhooks']>[string]`, which widens it to
`PathItemObject | ReferenceObject`. `openapi.test.ts` then failed
typecheck reading `.post` and `.post.parameters`, since a `ReferenceObject`
has neither. `satisfies` checks the literal against that same union without
widening the binding, so the object keeps its own concrete shape.
CI's Lint project job failed: `server/**/*.ts` now relies on Nitro's
auto-imports (`defineEventHandler`, `errors`, `taskStore`, ...), which
oxlint's `--type-aware --type-check` pass can only resolve once
`nuxt prepare` has generated `.nuxt/tsconfig.server.json` and its ambient
declarations. `typecheck` (`nuxt typecheck`) runs that step internally, and
`test` already had a `pretest: nuxt prepare` hook for the same reason, but
`lint`/`lint:fix` had no equivalent — so a clean checkout's first lint run
saw undeclared names and failed with 30 `Cannot find name` errors.

Add matching `prelint`/`prelint:fix` hooks, following the existing `pretest`
pattern in this same file. Verified by deleting `apps/dashboard/.nuxt` and
`node_modules/.cache/nuxt` (reproducing a cold checkout) and re-running
`aube run lint:ci`, `test`, `typecheck`, and `build` from that state: all
pass.
@vercel
vercel Bot temporarily deployed to Preview – agent-zero-docs August 18, 2026 20:02 Inactive
@kodiakhq
kodiakhq Bot merged commit de36669 into main Aug 18, 2026
19 of 20 checks passed
@kodiakhq
kodiakhq Bot deleted the t3code/align-dashboard-server branch August 18, 2026 20:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant