feat: tiered costs feature + admin tier management + tag selection
Build & Push Docker Image / build (push) Successful in 6m52s

- costs: nullable notes (fix create without notes), drop renewalDate
  (schema + API + UI), gate POST/PATCH/DELETE to admin + costs feature
- feature middleware: admin-aware hasFeature + getEntitlements union;
  /auth/me and login return resolved entitlements
- users: tier enum (free/premium/enterprise) in create/update/list,
  admin UI tier select + tier badge
- tags: GET /tags/all, TagInput autocomplete in new/edit tool forms,
  feature suggestions on focus, query invalidation on create/update
- openapi: nullable ToolUpdate urls, ToolUpdate tier fields, listAllTags
- Dockerfile: push-force to drop renewal_date column
This commit is contained in:
opencode
2026-08-02 01:10:47 +02:00
parent cd4efd16f6
commit 01c70085db
27 changed files with 478 additions and 86 deletions
+3
View File
@@ -4,6 +4,7 @@ import bcrypt from "bcryptjs";
import { eq } from "drizzle-orm";
import { db, usersTable } from "@workspace/db";
import { logger } from "../lib/logger";
import { getEntitlements } from "../middleware/feature";
const router: IRouter = Router();
@@ -155,6 +156,7 @@ router.post("/auth/login", async (req, res): Promise<void> => {
preferredUsername: user.username,
role: user.role,
tier: user.tier,
entitlements: getEntitlements(user.tier, user.role),
isLocal: true,
});
});
@@ -271,6 +273,7 @@ router.get("/auth/me", async (req, res): Promise<void> => {
preferredUsername: u.preferred_username ?? null,
role: u.role ?? "user",
tier: u.tier ?? "free",
entitlements: getEntitlements(u.tier, u.role),
isLocal: u.isLocal ?? false,
});
});