Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
32fccb3
feat: replace Hono + hono-openapi with a typed oRPC contract
nemvince Sep 30, 2026
0c99bdb
refactor(chronos): move each feature into a self-contained module folder
nemvince Sep 30, 2026
f53890b
fix(api): make the kiosk heartbeat response a plain union
nemvince Sep 30, 2026
4aaaf1d
refactor(chronos): let a module declare its own jobs and notifications
nemvince Sep 30, 2026
7b3faef
fix(iris): resolve the SSR origin through the proxy-aware accessor
nemvince Sep 30, 2026
aa7e4b7
fix(iris): restore SSR query hydration and the /api prefix
nemvince Sep 30, 2026
358b209
fix: add absolute api origin fallback
nemvince Oct 4, 2026
9756fed
chore: refresh dependencies and fold shared versions into the catalog
nemvince Oct 7, 2026
06ae5bc
fix(chronos): drop the better-auth account issuer column and default …
nemvince Oct 7, 2026
4ab0e8d
fix(telemetry): pin the data-collection categories instead of sendDef…
nemvince Oct 7, 2026
8b9f471
perf(iris): cache the i18next instance per language
nemvince Oct 7, 2026
d243556
fix(iris): import the global stylesheet from the root route
nemvince Oct 7, 2026
e6496d2
fix(iris): give the browser RPC client an absolute url
nemvince Oct 7, 2026
f4ff9a7
feat(iris): export substitutions and moved lessons to Excel with a da…
nemvince Oct 7, 2026
bd07598
refactor(iris): serve production with srvx instead of a custom server
nemvince Oct 7, 2026
f3e4c78
refactor(chronos): replace the hand-rolled API keys with better-auth'…
nemvince Oct 8, 2026
fe060a9
feat(api): add the admin procedures over every user's API keys
nemvince Oct 8, 2026
adba3af
feat(iris): add the user and admin API key screens
nemvince Oct 8, 2026
643eee2
feat(iris): show Empty component when no available timetable
nemvince Oct 8, 2026
6ca7075
fix(navigator): fix graph api preview returning 500
nemvince Oct 8, 2026
681edc0
feat: add petrikwifi integration
nemvince Oct 8, 2026
62ebf16
feat(iris): merge the settings page into a sectioned settings dialog
nemvince Oct 8, 2026
172febe
feat(iris): one timetable toolbar, and move appearance into settings
nemvince Oct 8, 2026
723f280
fix(iris): make the filter bar not shitty again
nemvince Oct 8, 2026
a959148
chore: update tailwind syntax and agent skills
nemvince Oct 8, 2026
4adbe4f
chore: replace husky with left-hook
nemvince Oct 8, 2026
f7274b6
feat: migrate to separate tsconfig package
nemvince Oct 12, 2026
21a5a50
feat: mail package with oauth
nemvince Oct 16, 2026
bc63527
feat: full tracing and get rid of logging holes
nemvince Oct 16, 2026
8ad2709
fix(chronos,iris): close a few holes, trace requests, dedupe contract…
nemvince Oct 16, 2026
a10f869
refactor: clear react-doctor findings and make the log usable
nemvince Oct 16, 2026
bdda477
Merge main into feat/orpc-rewrite-modules
nemvince Oct 16, 2026
d3e3835
fix: codeql bot suggestions
nemvince Oct 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
17 changes: 9 additions & 8 deletions .agents/skills/chronos-route-procedure/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
---
name: chronos-route-procedure
description: Procedures for adding or changing Chronos API routes, Hono handlers, validators, OpenAPI metadata, authentication or authorization middleware, or feature router registration in apps/chronos/src/routes. Use when creating endpoints, wiring zod validators, describing responses with hono-openapi, or registering routers.
description: Procedures for adding or changing Chronos API endpoints — oRPC contract procedures, module handlers, router registration, error responses, authentication or authorization middleware, or OpenAPI metadata. Use when creating endpoints in the oRPC stack, wiring validation schemas, or exposing a new feature on the API.
---
# Chronos Route Procedure

- Keep route work inside the feature folder under `apps/chronos/src/routes`, following the `_factory.ts`, `_router.ts`, and handler-file pattern used in `apps/chronos/src/routes/doorlock`.
- Match handler structure from files like `apps/chronos/src/routes/ping/index.ts`: `describeRoute(...)` first, then shared middleware, then validators, then the final handler.
- Request/response zod wire schemas live in `packages/api/src/domains/<domain>` (`@filcdev/api/domains/<name>`) so client apps share them — import from there instead of re-declaring. Schemas derived from Drizzle tables stay local to Chronos. Purely local helper schemas stay close to the route that uses them.
- Use `requireAuthentication` and `requireAuthorization(permissions.<name>)` middleware instead of inline permission checks; constants come from `@filcdev/api/permissions`. Never inline `'resource:action'` string literals.
- Return the established success envelope via the `ok()` helpers in `apps/chronos/src/utils/http.ts`; use `HTTPException` plus `StatusCodes` for error paths.
- Register every endpoint in the feature router (`_router.ts`) so the handler is reachable; do not wire ad hoc routes across the app.
- Ship complete OpenAPI metadata with the route change: tags via `filcExt(...)`, descriptions, and response documentation via `resolver(...)`.
- Endpoints are oRPC procedures, not Hono routes. The contract is the single source of truth: declare one procedure per endpoint in `packages/api/src/contract/<feature>.ts` as `oc.route(filcRoute({...})).input(...).output(...)`. `filcRoute` carries `method`, `path`, `operationId`, `tags`, `successStatus` and `auth` — copy the pattern from `packages/api/src/contract/users.ts`. There are no `x-filc_*` extensions to fill in: authentication is the document's `sessionAuth` scheme, and the client derives everything else from the schemas.
- `.output(...)` is mandatory on every procedure. `.input(...)` is ONE flat object — path params plus query (GET) or the JSON body (POST/PUT/PATCH) — with the same field names as the wire.
- Implement handlers in the feature folder under `apps/chronos/src/modules/<feature>`: handler files, a `_router.ts` exporting a plain object literal mirroring the contract nesting, `schema.ts`, and a `_module.ts` manifest when the feature owns jobs or notifications. Handler shape: `base.<feature>.<procedure>.handler(async ({ input, context }) => payload)` where `base` is `implement(appContract)` from `apps/chronos/src/orpc.ts` — see `apps/chronos/src/modules/ping/index.ts`.
- Register every handler in the feature's `_router.ts`; the full contract is assembled once via `base.router({...})` in `apps/chronos/src/router.ts`. A missing, extra or mistyped procedure fails `tsc` rather than 404ing at runtime.
- Success is `return payload` — there is no `{ success, data }` envelope. Errors are thrown `ORPCError`s: the helpers in `apps/chronos/src/utils/http.ts` (`notFound`, `conflict`, `badRequest`, `forbidden`, `unauthorized`, `badGateway`, `serviceUnavailable`) or the `errors.<CODE>(...)` factories from the shared error map in `packages/api/src/errors.ts`. Never use `HTTPException`, `StatusCodes`, or an `ok()` wrapper — they no longer exist.
- Use `requireAuthentication` and `requireAuthorization(permissions.<name>)` from `apps/chronos/src/middleware/auth.ts` instead of inline permission checks; constants come from `@filcdev/api/permissions`. Never inline `'resource:action'` string literals.
- Request/response zod wire schemas live in `packages/api/src/domains/<domain>` (`@filcdev/api/domains/<name>`) so client apps share them — import from there instead of re-declaring. Schemas derived from Drizzle tables stay local to Chronos.
- OpenAPI metadata ships with the contract change, not the handler. After touching any contract file, regenerate the document: `bun run openapi:generate` in `apps/chronos` (rewrites `openapi/chronos-openapi.json`, served at `/api/doc/openapi.json`).
12 changes: 6 additions & 6 deletions .agents/skills/chronos-schema-procedure/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
---
name: chronos-schema-procedure
description: Procedures for editing Chronos Drizzle schema files, table relationships, indexes, timestamps, and preparing migrations from apps/chronos/src/database/schema. Use when adding or altering tables or columns, changing relations, or generating database migrations.
description: Procedures for editing Chronos Drizzle schema tables, columns, relations, indexes, or generating database migrations. Use when adding or altering tables or columns in module schemas, changing relations, or preparing migrations with the db:* scripts.
---
# Chronos Schema Procedure

- Change TypeScript schema sources under `apps/chronos/src/database/schema`; never hand-edit generated SQL under `apps/chronos/src/database/migrations`.
- Feature tables live in `apps/chronos/src/modules/<feature>/schema.ts`; only the shared identity and RBAC tables stay in `apps/chronos/src/database/schema` (`authentication.ts`, `authorization.ts`, `api-keys.ts` — every other table has a foreign key to them). Never hand-edit generated SQL under `apps/chronos/src/database/migrations`.
- Reuse shared column helpers from `apps/chronos/src/database/helpers.ts` instead of re-declaring timestamp columns.
- Follow the table style in `apps/chronos/src/database/schema/doorlock.ts`: explicit foreign keys, intentional `onDelete` behavior, and indexes or composite keys where the relationship needs them.
- Keep exported schema collections updated when a new table belongs to an existing domain module.
- After intentional schema changes, generate the migration with the `db:*` scripts from `apps/chronos/package.json`.
- If backend route or frontend form code depends on a changed shape, update those callers in the same change rather than leaving the repo in a contract mismatch. Wire-facing response shapes may belong in `packages/api/src/domains` — update those contracts together with the tables.
- Follow the table style in `apps/chronos/src/modules/doorlock/schema.ts`: explicit foreign keys, intentional `onDelete` behavior, and indexes or composite keys where the relationship needs them.
- A module's tables are exported as a schema map from its `schema.ts` and MUST be added to `moduleSchemas` in `apps/chronos/src/modules/schemas.ts` — that list is what Drizzle's runtime schema is built from (it stays separate from the module manifests so `database/index.ts` can import it without creating an import cycle).
- After intentional schema changes, generate the migration with the `db:*` scripts in `apps/chronos/package.json`.
- If backend route or frontend form code depends on a changed shape, update those callers in the same change rather than leaving a contract mismatch. Wire-facing response shapes live in `packages/api/src/domains` — update those contracts together with the tables.
4 changes: 2 additions & 2 deletions .agents/skills/iris-data-flow/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: Procedures for adding or changing Iris route pages, React Query que

- Follow route composition patterns from files like `apps/iris/src/routes/_private/admin/timetable/substitutions.tsx`: `createFileRoute(...)` at the top, then permission gating, then page state (sort/filters/dialogs) fed by domain hooks.
- Domain data access lives in hook modules at `apps/iris/src/hooks/<domain>.ts` (see `substitutions.ts`): `use<X>` query hooks plus `useCreateX`/`useUpdateX`/`useDeleteX` mutation hooks. Hooks own the API call, translated toasts, and invalidation of every affected family; mutation hooks take `{ onSaved?: () => void }`.
- Routes contain no inline `parseResponse`/`useMutation` blocks — they consume the domain hooks and keep only UI state (sort, filters, dialog open/close, selection). Reference: `apps/iris/src/routes/_private/admin/timetable/substitutions.tsx`.
- Multi-parameter query keys take a single object argument (e.g. `queryKeys.doorlock.logs({ deviceFilter, search, ... })`) so React Query partial matching works.
- Routes contain no inline `useMutation` blocks — they consume the domain hooks and keep only UI state (sort, filters, dialog open/close, selection). Reference: `apps/iris/src/routes/_private/admin/timetable/substitutions.tsx`.
- There are no hand-written query keys. Queries use `orpc.<feature>.<procedure>.queryOptions({ input })` and invalidation uses `queryClient.invalidateQueries({ queryKey: orpc.<feature>.<procedure>.key({ input }) })` — a bare `.key()` matches every input of that procedure, and `queryKey: [...orpc.x.y.key({...}), extra]` scopes beyond the procedure's own input (see `apps/iris/src/hooks/notifications.ts`).
- Reuse `apps/iris/src/hooks/use-has-permission.ts` and existing permission guard components instead of duplicating permission logic in views; permission constants come from `@filcdev/api/permissions`.
- New user-facing error and success messages go through `t(...)` and both locale trees (`apps/iris/public/locales/en`, `apps/iris/public/locales/hu`), even when surfaced through toasts.
8 changes: 0 additions & 8 deletions .husky/install.ts

This file was deleted.

11 changes: 0 additions & 11 deletions .husky/pre-commit

This file was deleted.

Loading
Loading