feat(hub): capability connection admin API + UI (ADR-0027)

Adds the admin surface for managing org-scoped capability credentials,
so operators can configure the Aliyun docmind AccessKey from the web UI
instead of needing a CLI or database access.

Backend:
- CapabilityConnectionService: rotate/list/read/disable, mirroring
  FeishuApplicationConnectionService but keyed by (orgId, capabilityId)
- capabilityReadiness: probeDocmindCredential validates the AccessKey by
  calling QueryDocParserStatus with a dummy id (400 = auth ok, 401/403 = bad)
- Admin routes: GET/PUT/DELETE /api/org/:slug/capability-connections/:capId
  + GET list, wired into orgRoutes

Frontend:
- api.ts: CapabilityConnection type + capabilityConnections/rotate/disable
  client methods
- /admin/org/:slug/capabilities page: lists known capabilities
  (pdf_to_md_bundle, audio_video_to_text), shows status/version/keyId,
  inline rotate/disable forms with AccessKey ID/Secret/Endpoint fields
- Nav item '能力' added to sidebar

Version bump 0.0.31 → 0.0.32.
This commit is contained in:
2026-07-18 17:55:54 +08:00
parent 5e10419fc8
commit 251ad43ca2
8 changed files with 706 additions and 1 deletions
+11
View File
@@ -22,6 +22,8 @@ import type { LocalSecretEnvelope } from "../../security/secretEnvelope.js";
import type { ProviderReadinessProbe } from "../../connections/providerReadiness.js";
import type { FeishuReadinessProbe } from "../../connections/feishuReadiness.js";
import { registerFeishuApplicationConnectionRoutes } from "./feishuApplicationConnectionRoutes.js";
import { registerCapabilityConnectionRoutes } from "./capabilityConnectionRoutes.js";
import type { CapabilityReadinessProbe } from "../../capability/capabilityReadiness.js";
export interface OrgRouteConfig {
readonly prisma: PrismaClient;
@@ -30,6 +32,7 @@ export interface OrgRouteConfig {
readonly secretEnvelope: LocalSecretEnvelope;
readonly providerReadinessProbe?: ProviderReadinessProbe;
readonly feishuConnectionReadinessProbe?: FeishuReadinessProbe;
readonly capabilityReadinessProbe?: CapabilityReadinessProbe;
}
export async function registerOrgRoutes(app: FastifyInstance, config: OrgRouteConfig): Promise<void> {
@@ -138,4 +141,12 @@ export async function registerOrgRoutes(app: FastifyInstance, config: OrgRouteCo
? { readinessProbe: config.feishuConnectionReadinessProbe }
: {}),
});
await registerCapabilityConnectionRoutes(app, {
prisma: config.prisma,
sessionSecret: config.sessionSecret,
secretEnvelope: config.secretEnvelope,
...(config.capabilityReadinessProbe !== undefined
? { readinessProbe: config.capabilityReadinessProbe }
: {}),
});
}