@autional-cn/shared 0.1.0-rc.4 → 0.1.0-rc.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/api/__tests__/namespace.test.ts +27 -0
- package/src/api/client.ts +7 -1
- package/src/api/namespace.ts +14 -0
- package/src/config/index.ts +4 -0
- package/src/generated/api.ts +28 -4
- package/src/generated/queries.ts +20 -1
- package/src/generated/types.ts +93 -50
- package/src/vite-env.d.ts +1 -0
package/package.json
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { needsNamespaceHeader } from '../namespace';
|
|
3
|
+
|
|
4
|
+
describe('needsNamespaceHeader', () => {
|
|
5
|
+
it('密钥 admin 组端点(列表/子路径/查询)需注 X-Namespace', () => {
|
|
6
|
+
expect(needsNamespaceHeader('/secret/api/v1/admin/secrets')).toBe(true);
|
|
7
|
+
expect(needsNamespaceHeader('/secret/api/v1/admin/secrets/detail?key=a/b')).toBe(true);
|
|
8
|
+
expect(needsNamespaceHeader('/secret/api/v1/admin/secrets/batch-delete')).toBe(true);
|
|
9
|
+
expect(needsNamespaceHeader('/secret/api/v1/admin/secrets/policy')).toBe(true);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('非密钥 admin 端点不注头', () => {
|
|
13
|
+
expect(needsNamespaceHeader('/notification/api/v1/admin/announcements')).toBe(false);
|
|
14
|
+
expect(needsNamespaceHeader('/tenant/api/v1/admin/tenants')).toBe(false);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('secret 公开面/internal 面不注头(前端不消费)', () => {
|
|
18
|
+
expect(needsNamespaceHeader('/secret/public/jwt/public-key')).toBe(false);
|
|
19
|
+
expect(needsNamespaceHeader('/secret/api/v1/secret/public/transmission/public-key')).toBe(false);
|
|
20
|
+
expect(needsNamespaceHeader('/api/v1/internal/secret/jwt/keys')).toBe(false);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('相对路径缺省(undefined/空)不注头', () => {
|
|
24
|
+
expect(needsNamespaceHeader(undefined)).toBe(false);
|
|
25
|
+
expect(needsNamespaceHeader('')).toBe(false);
|
|
26
|
+
});
|
|
27
|
+
});
|
package/src/api/client.ts
CHANGED
|
@@ -9,9 +9,10 @@
|
|
|
9
9
|
import axios, { AxiosError } from 'axios';
|
|
10
10
|
import type { AxiosInstance, InternalAxiosRequestConfig } from 'axios';
|
|
11
11
|
import { camelCaseKeys, snakeCaseKeys } from '../utils/case';
|
|
12
|
-
import { getApiBaseUrl } from '../config';
|
|
12
|
+
import { API_NAMESPACE, getApiBaseUrl } from '../config';
|
|
13
13
|
import { getTraceParentHeader } from './trace';
|
|
14
14
|
import { ENTRY_PLANE_HEADER, resolveEntryPlane } from './entry-plane';
|
|
15
|
+
import { NAMESPACE_HEADER, needsNamespaceHeader } from './namespace';
|
|
15
16
|
import { AuthService } from '../auth/service';
|
|
16
17
|
|
|
17
18
|
function setupInterceptors(instance: AxiosInstance) {
|
|
@@ -39,6 +40,11 @@ function setupInterceptors(instance: AxiosInstance) {
|
|
|
39
40
|
config.headers['X-Tenant-ID'] = tenantId;
|
|
40
41
|
}
|
|
41
42
|
|
|
43
|
+
// secret 管理面(§13-A P1-B):admin 组端点 fail-closed 要求 X-Namespace ∈ S
|
|
44
|
+
if (needsNamespaceHeader(config.url)) {
|
|
45
|
+
config.headers[NAMESPACE_HEADER] = API_NAMESPACE;
|
|
46
|
+
}
|
|
47
|
+
|
|
42
48
|
// 请求体 camelCase → snake_case 转换(后端 Go 期望 snake_case)
|
|
43
49
|
if (config.data && typeof config.data === 'object' && !(config.data instanceof FormData)) {
|
|
44
50
|
config.data = snakeCaseKeys(config.data);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* secret 服务管理面 namespace(§13-A P1-B / SEC-204/207):
|
|
3
|
+
* `/secret/api/v1/admin*` 端点 fail-closed 要求 `X-Namespace ∈ 实例服务集合 S`
|
|
4
|
+
* (NamespaceMiddleware,缺头/未服务 → 400)。值取部署配置 VITE_API_NAMESPACE
|
|
5
|
+
* (见 config,缺省 "dev" 与服务端 DefaultNamespace 对称)。
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const NAMESPACE_HEADER = 'X-Namespace';
|
|
9
|
+
|
|
10
|
+
export const SECRET_ADMIN_PATH_PREFIX = '/secret/api/v1/admin';
|
|
11
|
+
|
|
12
|
+
export function needsNamespaceHeader(url?: string): boolean {
|
|
13
|
+
return !!url && url.includes(SECRET_ADMIN_PATH_PREFIX);
|
|
14
|
+
}
|
package/src/config/index.ts
CHANGED
|
@@ -356,6 +356,10 @@ export function getPLATFORM_CONSOLE_URL(): string {
|
|
|
356
356
|
}
|
|
357
357
|
export const API_BASE_URL = getEnv('VITE_API_BASE_URL', '/bff');
|
|
358
358
|
|
|
359
|
+
// secret 管理面 namespace(§13-A P1-B):admin 组端点要求 X-Namespace ∈ S(fail-closed);
|
|
360
|
+
// 缺省 "dev" 与服务端 DefaultNamespace(service-core cross/registry keyid.go)对称
|
|
361
|
+
export const API_NAMESPACE = getEnv('VITE_API_NAMESPACE', 'dev');
|
|
362
|
+
|
|
359
363
|
export function getApiBaseUrl(): string {
|
|
360
364
|
return API_BASE_URL;
|
|
361
365
|
}
|
package/src/generated/api.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Auto-generated from swagger.json annotations
|
|
2
2
|
// DO NOT EDIT — run `python scripts/generate_api_ts.py` to regenerate
|
|
3
|
-
// Generated: 2026-
|
|
3
|
+
// Generated: 2026-09-30 17:04:31
|
|
4
4
|
|
|
5
5
|
// @ts-nocheck — auto-generated; validated by check-generated-api.py
|
|
6
6
|
import type * as Types from './types';
|
|
@@ -6855,6 +6855,20 @@ export async function mfaWebauthnCredentialsByCredentialsPut(webauthnCredentialI
|
|
|
6855
6855
|
// Notification Service
|
|
6856
6856
|
// ============================================================
|
|
6857
6857
|
|
|
6858
|
+
/**
|
|
6859
|
+
* 管理端列出公告
|
|
6860
|
+
* 管理端分页查询本租户公告列表,支持按状态过滤和关键词搜索;与用户面 /announcements 同体(同租户范围),走 admin 受众供控制台读取 参考:CAN-SPAM Act (15 U.S.C. §7701) — Commercial Email Compliance。
|
|
6861
|
+
*/
|
|
6862
|
+
export async function adminAnnouncements(params?: {
|
|
6863
|
+
page?: number; // 页码
|
|
6864
|
+
page_size?: number; // 每页条数
|
|
6865
|
+
status?: string; // 状态过滤: draft/scheduled/published/expired
|
|
6866
|
+
search?: string; // 搜索关键词
|
|
6867
|
+
}) {
|
|
6868
|
+
const res = await api.get(`/notification/api/v1/admin/announcements`, { params });
|
|
6869
|
+
return res.data;
|
|
6870
|
+
}
|
|
6871
|
+
|
|
6858
6872
|
/**
|
|
6859
6873
|
* 创建公告
|
|
6860
6874
|
* 创建新的公告,支持草稿/定时发布,可指定目标租户和角色 参考:CAN-SPAM Act (15 U.S.C. §7701) — Commercial Email Compliance。
|
|
@@ -7224,15 +7238,25 @@ export async function notificationsStats() {
|
|
|
7224
7238
|
|
|
7225
7239
|
/**
|
|
7226
7240
|
* SSE实时通知流
|
|
7227
|
-
* 通过Server-Sent Events
|
|
7241
|
+
* 通过Server-Sent Events实时推送通知。P5-4:经 POST /notifications/stream-ticket 换取一次性票据后以 ?ticket= 建流(浏览器 EventSource 主路径);非浏览器客户端可走 Authorization 头 JWT(?token= 兼容回退已删除)。订阅身份以认证上下文(票据/JWT claims)为准。 参考:CAN-SPAM Act (15 U.S.C. §7701) — Commercial Email Compliance。
|
|
7228
7242
|
*/
|
|
7229
7243
|
export async function notificationsStream(params?: {
|
|
7230
|
-
|
|
7244
|
+
ticket?: string; // 一次性短期票据(P5-4 主路径,60s 内一次性消费)
|
|
7245
|
+
user_id?: string; // 用户ID(已弃用回退:仅在认证上下文无用户时使用)
|
|
7231
7246
|
}) {
|
|
7232
7247
|
const res = await api.get(`/notification/api/v1/notifications/stream`, { params });
|
|
7233
7248
|
return res.data;
|
|
7234
7249
|
}
|
|
7235
7250
|
|
|
7251
|
+
/**
|
|
7252
|
+
* 签发 SSE 短期票据
|
|
7253
|
+
* 为 /notifications/stream 签发一次性票据(P5-4):浏览器 EventSource 不能携带 Authorization 头,故以 JWT 保护的本端点换取 60s 一次性票据,再以 ?ticket= 建流,避免 access token 进入 URL/接入日志。需 JWT 认证(正常 Authorization 头调用)。
|
|
7254
|
+
*/
|
|
7255
|
+
export async function notificationsStreamTicketPost() {
|
|
7256
|
+
const res = await api.post(`/notification/api/v1/notifications/stream-ticket`);
|
|
7257
|
+
return res.data;
|
|
7258
|
+
}
|
|
7259
|
+
|
|
7236
7260
|
/**
|
|
7237
7261
|
* 列出通知模板
|
|
7238
7262
|
* 获取所有通知模板列表,支持包含已停用模板的选项 参考:CAN-SPAM Act (15 U.S.C. §7701) — Commercial Email Compliance。
|
|
@@ -7377,7 +7401,7 @@ export async function pushSubscriptionsBySubscriptions(subscriptionId: string) {
|
|
|
7377
7401
|
|
|
7378
7402
|
/**
|
|
7379
7403
|
* 获取 VAPID 公钥
|
|
7380
|
-
* 返回 Web Push VAPID 公钥,供前端注册 Push
|
|
7404
|
+
* 返回 Web Push VAPID 公钥,供前端注册 Push 订阅时使用(来源:communication-service) 参考:CAN-SPAM Act (15 U.S.C. §7701) — Commercial Email Compliance。
|
|
7381
7405
|
*/
|
|
7382
7406
|
export async function pushVapidPublicKey() {
|
|
7383
7407
|
const res = await api.get(`/notification/api/v1/push/vapid-public-key`);
|
package/src/generated/queries.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Auto-generated from swagger.json annotations
|
|
2
2
|
// DO NOT EDIT — run `python scripts/generate_api_ts.py` to regenerate
|
|
3
|
-
// Generated: 2026-
|
|
3
|
+
// Generated: 2026-09-30 17:04:31
|
|
4
4
|
|
|
5
5
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
6
6
|
import * as api from './api';
|
|
@@ -2599,6 +2599,14 @@ export function useMfaWebauthnCredentialsByCredentials(webauthnCredentialId: str
|
|
|
2599
2599
|
|
|
2600
2600
|
// --- notification-service ---
|
|
2601
2601
|
|
|
2602
|
+
/** 管理端列出公告 */
|
|
2603
|
+
export function useAdminAnnouncements(params?: any) {
|
|
2604
|
+
return useQuery({
|
|
2605
|
+
queryKey: ['notification-service', params] as const,
|
|
2606
|
+
queryFn: () => api.adminAnnouncements(params),
|
|
2607
|
+
});
|
|
2608
|
+
}
|
|
2609
|
+
|
|
2602
2610
|
/** 管理员查看指定用户通知列表 */
|
|
2603
2611
|
export function useAdminNotifications(params?: any) {
|
|
2604
2612
|
return useQuery({
|
|
@@ -9153,6 +9161,17 @@ export function usePostNotificationsSend_from_template() {
|
|
|
9153
9161
|
});
|
|
9154
9162
|
}
|
|
9155
9163
|
|
|
9164
|
+
/** 签发 SSE 短期票据 */
|
|
9165
|
+
export function usePostNotificationsStream_ticket() {
|
|
9166
|
+
const qc = useQueryClient();
|
|
9167
|
+
return useMutation({
|
|
9168
|
+
mutationFn: () => api.notificationsStreamTicketPost(),
|
|
9169
|
+
onSuccess: () => {
|
|
9170
|
+
qc.invalidateQueries({ queryKey: ['notification-service'] });
|
|
9171
|
+
},
|
|
9172
|
+
});
|
|
9173
|
+
}
|
|
9174
|
+
|
|
9156
9175
|
/** 发送测试通知 */
|
|
9157
9176
|
export function usePostNotificationsTest() {
|
|
9158
9177
|
const qc = useQueryClient();
|
package/src/generated/types.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Auto-generated from swagger.json annotations
|
|
2
2
|
// DO NOT EDIT — run `python scripts/generate_api_ts.py` to regenerate
|
|
3
|
-
// Generated: 2026-
|
|
3
|
+
// Generated: 2026-09-30 17:04:31
|
|
4
4
|
|
|
5
5
|
// ============================================================
|
|
6
6
|
// Shared generic types
|
|
@@ -7516,6 +7516,71 @@ export type COSEAlgorithmIdentifier = "-7" | "-8" | "-9" | "-19" | "-35" | "-36"
|
|
|
7516
7516
|
// notification-service
|
|
7517
7517
|
// ============================================================
|
|
7518
7518
|
|
|
7519
|
+
export interface DataResponsegitee_com_autional_servicenotification_internal_handler_dto_EventMappingResponse {
|
|
7520
|
+
code?: number;
|
|
7521
|
+
data?: EventMappingResponse;
|
|
7522
|
+
message?: string;
|
|
7523
|
+
timestamp?: string;
|
|
7524
|
+
}
|
|
7525
|
+
|
|
7526
|
+
export interface DataResponsegitee_com_autional_servicenotification_internal_handler_dto_ExportUserDataResponse {
|
|
7527
|
+
code?: number;
|
|
7528
|
+
data?: ExportUserDataResponse;
|
|
7529
|
+
message?: string;
|
|
7530
|
+
timestamp?: string;
|
|
7531
|
+
}
|
|
7532
|
+
|
|
7533
|
+
export interface DataResponsegitee_com_autional_servicenotification_internal_handler_dto_NotificationPreferencesResponse {
|
|
7534
|
+
code?: number;
|
|
7535
|
+
data?: NotificationPreferencesResponse;
|
|
7536
|
+
message?: string;
|
|
7537
|
+
timestamp?: string;
|
|
7538
|
+
}
|
|
7539
|
+
|
|
7540
|
+
export interface DataResponsegitee_com_autional_servicenotification_internal_handler_dto_NotificationResponse {
|
|
7541
|
+
code?: number;
|
|
7542
|
+
data?: NotificationResponse;
|
|
7543
|
+
message?: string;
|
|
7544
|
+
timestamp?: string;
|
|
7545
|
+
}
|
|
7546
|
+
|
|
7547
|
+
export interface DataResponsegitee_com_autional_servicenotification_internal_handler_dto_StreamTicketResponse {
|
|
7548
|
+
code?: number;
|
|
7549
|
+
data?: StreamTicketResponse;
|
|
7550
|
+
message?: string;
|
|
7551
|
+
timestamp?: string;
|
|
7552
|
+
}
|
|
7553
|
+
|
|
7554
|
+
export interface DataResponsegitee_com_autional_servicenotification_internal_handler_dto_TemplateResponse {
|
|
7555
|
+
code?: number;
|
|
7556
|
+
data?: TemplateResponse;
|
|
7557
|
+
message?: string;
|
|
7558
|
+
timestamp?: string;
|
|
7559
|
+
}
|
|
7560
|
+
|
|
7561
|
+
export interface DataResponsehandler_HealthErrorResponse {
|
|
7562
|
+
code?: number;
|
|
7563
|
+
data?: HealthErrorResponse;
|
|
7564
|
+
message?: string;
|
|
7565
|
+
timestamp?: string;
|
|
7566
|
+
}
|
|
7567
|
+
|
|
7568
|
+
export interface DataResponsemap_string_string {
|
|
7569
|
+
code?: number;
|
|
7570
|
+
data?: Map_string_string;
|
|
7571
|
+
message?: string;
|
|
7572
|
+
timestamp?: string;
|
|
7573
|
+
}
|
|
7574
|
+
|
|
7575
|
+
export interface ListResponsegitee_com_autional_servicenotification_internal_handler_dto_NotificationResponse {
|
|
7576
|
+
code?: number;
|
|
7577
|
+
items?: NotificationResponse[]; // 统一使用 items
|
|
7578
|
+
message?: string;
|
|
7579
|
+
pagination?: PageInfo; // 分页信息(嵌套对象)
|
|
7580
|
+
timestamp?: string;
|
|
7581
|
+
total?: number; // 总条数(平铺,便于直接读取)
|
|
7582
|
+
}
|
|
7583
|
+
|
|
7519
7584
|
export interface AnnouncementDetailResponse {
|
|
7520
7585
|
code?: number;
|
|
7521
7586
|
data?: AnnouncementResponse;
|
|
@@ -7641,48 +7706,6 @@ export interface CreateGlobalVariableRequest {
|
|
|
7641
7706
|
value: string;
|
|
7642
7707
|
}
|
|
7643
7708
|
|
|
7644
|
-
export interface DataResponsedto_ExportUserDataResponse {
|
|
7645
|
-
code?: number;
|
|
7646
|
-
data?: ExportUserDataResponse;
|
|
7647
|
-
message?: string;
|
|
7648
|
-
timestamp?: string;
|
|
7649
|
-
}
|
|
7650
|
-
|
|
7651
|
-
export interface DataResponsedto_NotificationPreferencesResponse {
|
|
7652
|
-
code?: number;
|
|
7653
|
-
data?: NotificationPreferencesResponse;
|
|
7654
|
-
message?: string;
|
|
7655
|
-
timestamp?: string;
|
|
7656
|
-
}
|
|
7657
|
-
|
|
7658
|
-
export interface DataResponsedto_NotificationResponse {
|
|
7659
|
-
code?: number;
|
|
7660
|
-
data?: NotificationResponse;
|
|
7661
|
-
message?: string;
|
|
7662
|
-
timestamp?: string;
|
|
7663
|
-
}
|
|
7664
|
-
|
|
7665
|
-
export interface DataResponsedto_TemplateResponse {
|
|
7666
|
-
code?: number;
|
|
7667
|
-
data?: TemplateResponse;
|
|
7668
|
-
message?: string;
|
|
7669
|
-
timestamp?: string;
|
|
7670
|
-
}
|
|
7671
|
-
|
|
7672
|
-
export interface DataResponsehandler_HealthErrorResponse {
|
|
7673
|
-
code?: number;
|
|
7674
|
-
data?: HealthErrorResponse;
|
|
7675
|
-
message?: string;
|
|
7676
|
-
timestamp?: string;
|
|
7677
|
-
}
|
|
7678
|
-
|
|
7679
|
-
export interface DataResponsemap_string_string {
|
|
7680
|
-
code?: number;
|
|
7681
|
-
data?: Map_string_string;
|
|
7682
|
-
message?: string;
|
|
7683
|
-
timestamp?: string;
|
|
7684
|
-
}
|
|
7685
|
-
|
|
7686
7709
|
export interface DeleteNotificationDetailResponse {
|
|
7687
7710
|
code?: number;
|
|
7688
7711
|
data?: DeleteNotificationResponse;
|
|
@@ -7776,13 +7799,20 @@ export interface InternalPushSendRequest {
|
|
|
7776
7799
|
userId?: string; // @example user-001
|
|
7777
7800
|
}
|
|
7778
7801
|
|
|
7779
|
-
export interface
|
|
7780
|
-
|
|
7781
|
-
|
|
7782
|
-
|
|
7783
|
-
|
|
7784
|
-
|
|
7785
|
-
|
|
7802
|
+
export interface InternalSendExternalRequest {
|
|
7803
|
+
channel: string; // @example email
|
|
7804
|
+
locale?: string; // @example en-US
|
|
7805
|
+
recipient: string; // @example user@example.com
|
|
7806
|
+
templateCode: string; // @example status_subscription_confirm
|
|
7807
|
+
variables?: Record<string, string>;
|
|
7808
|
+
}
|
|
7809
|
+
|
|
7810
|
+
export interface InternalUpsertEventMappingRequest {
|
|
7811
|
+
channel?: string; // 空 → in_app | @example in_app
|
|
7812
|
+
eventType: string; // @example user.registered
|
|
7813
|
+
isEnabled?: boolean; // 空 → true
|
|
7814
|
+
priority?: string; // 空 → medium | @example medium
|
|
7815
|
+
templateCode: string; // @example welcome
|
|
7786
7816
|
}
|
|
7787
7817
|
|
|
7788
7818
|
export interface MarkReadDetailResponse {
|
|
@@ -8008,6 +8038,12 @@ export interface SendNotificationRequest {
|
|
|
8008
8038
|
userId: string; // 用户ID | @example usr_abc123
|
|
8009
8039
|
}
|
|
8010
8040
|
|
|
8041
|
+
/** 一次性 SSE 票据:60s 内有效、消费一次即失效;以 ?ticket= 建立 EventSource 流 */
|
|
8042
|
+
export interface StreamTicketResponse {
|
|
8043
|
+
expiresIn?: number; // 有效期(秒) | @example 60
|
|
8044
|
+
ticket?: string; // 一次性票据 | @example 1B2c3D4e5F6g7H8i9J0k1L2m3N4o5P6q7R8s9T0u1V2
|
|
8045
|
+
}
|
|
8046
|
+
|
|
8011
8047
|
export interface TestNotificationDetailResponse {
|
|
8012
8048
|
code?: number;
|
|
8013
8049
|
data?: TestNotificationResponse;
|
|
@@ -8873,6 +8909,13 @@ export interface DataResponsedomain_PointIntegrityResult {
|
|
|
8873
8909
|
timestamp?: string;
|
|
8874
8910
|
}
|
|
8875
8911
|
|
|
8912
|
+
export interface DataResponsedto_ExportUserDataResponse {
|
|
8913
|
+
code?: number;
|
|
8914
|
+
data?: ExportUserDataResponse;
|
|
8915
|
+
message?: string;
|
|
8916
|
+
timestamp?: string;
|
|
8917
|
+
}
|
|
8918
|
+
|
|
8876
8919
|
export interface DeleteUserDataRequest {
|
|
8877
8920
|
userId: string;
|
|
8878
8921
|
}
|
package/src/vite-env.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ interface ImportMetaEnv {
|
|
|
9
9
|
readonly VITE_OAUTH_CLIENT_ID: string;
|
|
10
10
|
readonly VITE_AUTH_PAGES_URL: string;
|
|
11
11
|
readonly VITE_API_BASE_URL: string;
|
|
12
|
+
readonly VITE_API_NAMESPACE: string;
|
|
12
13
|
readonly VITE_AUDIT_BASE_URL: string;
|
|
13
14
|
[key: string]: string | boolean | undefined;
|
|
14
15
|
}
|