feat(assets): add dimension analysis and authorized user previews
ci/woodpecker/push/woodpecker Pipeline was successful

Refactor asset drilldowns with combined dimension filters, parent summaries and progressive loading. Add the hidden /who read-only permission preview with scoped authorization, identity mapping and audit logging. Refine inventory counts and AI问数 presentation.
This commit is contained in:
shishengliang
2026-09-28 12:29:51 +08:00
parent 6de77adb47
commit f1b3f8d3da
69 changed files with 3871 additions and 536 deletions
+9 -4
View File
@@ -59,6 +59,7 @@ router.get("/gaps", async (c) => {
return c.json({
items: await gapStore.list(
c.req.query("scope") === "all" ? null : user.userId,
{ readOnly: !!user.preview },
),
canManage: manage,
});
@@ -502,8 +503,10 @@ router.post("/ask", async (c) => {
if (unanswered?.length) demand = `${unanswered.map(item => `${item.question}:${item.reason}`).join(";")}(原问题:${demand})`.slice(0, 600);
let recorded = false;
try {
await gapStore.record(user.userId, demand, gapReason);
recorded = true;
if (!user.preview) {
await gapStore.record(user.userId, demand, gapReason);
recorded = true;
}
} catch {
/* Report failure explicitly, never pretend it was persisted. */
}
@@ -518,8 +521,10 @@ router.post("/ask", async (c) => {
if (!controller.signal.aborted) {
let recorded = false;
try {
await gapStore.record(user.userId, demand, "generation");
recorded = true;
if (!user.preview) {
await gapStore.record(user.userId, demand, "generation");
recorded = true;
}
} catch {
/* No raw error or query payload in logs. */
}