@superblocksteam/shared 0.9590.8 → 0.9591.0
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/dist/database-lifecycle/index.d.ts +33 -74
- package/dist/database-lifecycle/index.d.ts.map +1 -1
- package/dist/database-lifecycle/index.js +33 -31
- package/dist/database-lifecycle/index.js.map +1 -1
- package/dist/database-lifecycle/index.test.js +6 -6
- package/dist/database-lifecycle/index.test.js.map +1 -1
- package/dist/socket/protocol.d.ts +16 -2
- package/dist/socket/protocol.d.ts.map +1 -1
- package/dist/socket/protocol.js.map +1 -1
- package/dist/types/ai/index.d.ts +1 -0
- package/dist/types/ai/index.d.ts.map +1 -1
- package/dist/types/ai/index.js +1 -0
- package/dist/types/ai/index.js.map +1 -1
- package/dist/types/ai/quota-paywall.d.ts +8 -0
- package/dist/types/ai/quota-paywall.d.ts.map +1 -1
- package/dist/types/ai/quota-paywall.js +19 -1
- package/dist/types/ai/quota-paywall.js.map +1 -1
- package/dist/types/ai/safety-classification.d.ts +16 -0
- package/dist/types/ai/safety-classification.d.ts.map +1 -0
- package/dist/types/ai/safety-classification.js +22 -0
- package/dist/types/ai/safety-classification.js.map +1 -0
- package/dist/types/application/index.d.ts +15 -0
- package/dist/types/application/index.d.ts.map +1 -1
- package/dist/types/application/index.js.map +1 -1
- package/dist/types/audit/ocsf.d.ts +32 -0
- package/dist/types/audit/ocsf.d.ts.map +1 -1
- package/dist/types/audit/ocsf.js +2 -0
- package/dist/types/audit/ocsf.js.map +1 -1
- package/dist/types/billing/billing.d.ts +1 -0
- package/dist/types/billing/billing.d.ts.map +1 -1
- package/dist/types/billing/billing.js +10 -0
- package/dist/types/billing/billing.js.map +1 -1
- package/dist/types/billing/index.d.ts +1 -0
- package/dist/types/billing/index.d.ts.map +1 -1
- package/dist/types/billing/index.js +1 -0
- package/dist/types/billing/index.js.map +1 -1
- package/dist/types/billing/spendAlert.d.ts +62 -0
- package/dist/types/billing/spendAlert.d.ts.map +1 -0
- package/dist/types/billing/spendAlert.js +11 -0
- package/dist/types/billing/spendAlert.js.map +1 -0
- package/dist/types/policyGate/index.d.ts +24 -0
- package/dist/types/policyGate/index.d.ts.map +1 -1
- package/dist/types/policyGate/index.js +9 -0
- package/dist/types/policyGate/index.js.map +1 -1
- package/dist/types/rbac/index.d.ts +4 -0
- package/dist/types/rbac/index.d.ts.map +1 -1
- package/dist/types/rbac/index.js +4 -0
- package/dist/types/rbac/index.js.map +1 -1
- package/dist/types/reviewPolicy/index.d.ts +9 -3
- package/dist/types/reviewPolicy/index.d.ts.map +1 -1
- package/dist/types/reviewPolicy/index.js +5 -1
- package/dist/types/reviewPolicy/index.js.map +1 -1
- package/dist-esm/database-lifecycle/index.d.ts +33 -74
- package/dist-esm/database-lifecycle/index.d.ts.map +1 -1
- package/dist-esm/database-lifecycle/index.js +32 -29
- package/dist-esm/database-lifecycle/index.js.map +1 -1
- package/dist-esm/database-lifecycle/index.test.js +6 -6
- package/dist-esm/database-lifecycle/index.test.js.map +1 -1
- package/dist-esm/socket/protocol.d.ts +16 -2
- package/dist-esm/socket/protocol.d.ts.map +1 -1
- package/dist-esm/socket/protocol.js.map +1 -1
- package/dist-esm/types/ai/index.d.ts +1 -0
- package/dist-esm/types/ai/index.d.ts.map +1 -1
- package/dist-esm/types/ai/index.js +1 -0
- package/dist-esm/types/ai/index.js.map +1 -1
- package/dist-esm/types/ai/quota-paywall.d.ts +8 -0
- package/dist-esm/types/ai/quota-paywall.d.ts.map +1 -1
- package/dist-esm/types/ai/quota-paywall.js +17 -0
- package/dist-esm/types/ai/quota-paywall.js.map +1 -1
- package/dist-esm/types/ai/safety-classification.d.ts +16 -0
- package/dist-esm/types/ai/safety-classification.d.ts.map +1 -0
- package/dist-esm/types/ai/safety-classification.js +19 -0
- package/dist-esm/types/ai/safety-classification.js.map +1 -0
- package/dist-esm/types/application/index.d.ts +15 -0
- package/dist-esm/types/application/index.d.ts.map +1 -1
- package/dist-esm/types/application/index.js.map +1 -1
- package/dist-esm/types/audit/ocsf.d.ts +32 -0
- package/dist-esm/types/audit/ocsf.d.ts.map +1 -1
- package/dist-esm/types/audit/ocsf.js +2 -0
- package/dist-esm/types/audit/ocsf.js.map +1 -1
- package/dist-esm/types/billing/billing.d.ts +1 -0
- package/dist-esm/types/billing/billing.d.ts.map +1 -1
- package/dist-esm/types/billing/billing.js +9 -0
- package/dist-esm/types/billing/billing.js.map +1 -1
- package/dist-esm/types/billing/index.d.ts +1 -0
- package/dist-esm/types/billing/index.d.ts.map +1 -1
- package/dist-esm/types/billing/index.js +1 -0
- package/dist-esm/types/billing/index.js.map +1 -1
- package/dist-esm/types/billing/spendAlert.d.ts +62 -0
- package/dist-esm/types/billing/spendAlert.d.ts.map +1 -0
- package/dist-esm/types/billing/spendAlert.js +10 -0
- package/dist-esm/types/billing/spendAlert.js.map +1 -0
- package/dist-esm/types/policyGate/index.d.ts +24 -0
- package/dist-esm/types/policyGate/index.d.ts.map +1 -1
- package/dist-esm/types/policyGate/index.js +8 -1
- package/dist-esm/types/policyGate/index.js.map +1 -1
- package/dist-esm/types/rbac/index.d.ts +4 -0
- package/dist-esm/types/rbac/index.d.ts.map +1 -1
- package/dist-esm/types/rbac/index.js +4 -0
- package/dist-esm/types/rbac/index.js.map +1 -1
- package/dist-esm/types/reviewPolicy/index.d.ts +9 -3
- package/dist-esm/types/reviewPolicy/index.d.ts.map +1 -1
- package/dist-esm/types/reviewPolicy/index.js +4 -0
- package/dist-esm/types/reviewPolicy/index.js.map +1 -1
- package/package.json +2 -2
- package/src/database-lifecycle/index.test.ts +6 -6
- package/src/database-lifecycle/index.ts +76 -152
- package/src/socket/protocol.ts +22 -4
- package/src/types/ai/index.ts +1 -0
- package/src/types/ai/quota-paywall.ts +20 -0
- package/src/types/ai/safety-classification.ts +27 -0
- package/src/types/application/index.ts +16 -0
- package/src/types/audit/ocsf.ts +43 -0
- package/src/types/billing/billing.ts +11 -0
- package/src/types/billing/index.ts +1 -0
- package/src/types/billing/spendAlert.ts +84 -0
- package/src/types/policyGate/index.ts +28 -0
- package/src/types/rbac/index.ts +4 -0
- package/src/types/reviewPolicy/index.ts +13 -3
package/src/types/audit/ocsf.ts
CHANGED
|
@@ -163,6 +163,7 @@ export const AUDIT_EVENT_TYPE_CATALOG: AuditEventTypeEntry[] = [
|
|
|
163
163
|
'application.git.connect',
|
|
164
164
|
'application.git.disconnect',
|
|
165
165
|
'application.metadata.update',
|
|
166
|
+
'application.policy_gate_check.start',
|
|
166
167
|
'application.settings.update',
|
|
167
168
|
'application.undeploy'
|
|
168
169
|
]
|
|
@@ -237,6 +238,7 @@ export const AUDIT_EVENT_TYPE_CATALOG: AuditEventTypeEntry[] = [
|
|
|
237
238
|
resource_type: 'Organization',
|
|
238
239
|
operations: [
|
|
239
240
|
'organization.npm_allow_install_scripts_changed',
|
|
241
|
+
'organization.npm_install.blocked',
|
|
240
242
|
'organization.npm_registry.create',
|
|
241
243
|
'organization.npm_registry.delete',
|
|
242
244
|
'organization.npm_registry.update',
|
|
@@ -339,3 +341,44 @@ const METADATA: Omit<OCSFMetadata, 'log_name'> = {
|
|
|
339
341
|
export function buildOCSFMetadata(logName: string): OCSFMetadata {
|
|
340
342
|
return { ...METADATA, log_name: logName };
|
|
341
343
|
}
|
|
344
|
+
|
|
345
|
+
// ---------------------------------------------------------------------------
|
|
346
|
+
// npm install-blocked audit report (APPS-4191 / P6.3)
|
|
347
|
+
// ---------------------------------------------------------------------------
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Wire payload for the `v1.audit.npmInstallBlocked` socket method.
|
|
351
|
+
*
|
|
352
|
+
* Emitted by the Clark dev-server runtime when the controlled install path
|
|
353
|
+
* reports `NpmInstallBlocked`. The server derives org + actor from the
|
|
354
|
+
* authenticated connection (never trusting the client for identity),
|
|
355
|
+
* throttles per-org and globally, sanitizes via the P6.1 telemetry helpers,
|
|
356
|
+
* and writes an OCSF `audit_event` row with operation
|
|
357
|
+
* `organization.npm_install.blocked`.
|
|
358
|
+
*
|
|
359
|
+
* Carries only structured, low-risk fields — deliberately NO free-text error
|
|
360
|
+
* message, so a registry token embedded in CLI output can never reach the wire.
|
|
361
|
+
*/
|
|
362
|
+
export interface NpmInstallBlockedAuditReport {
|
|
363
|
+
/** `NpmInstallBlocked.reason`; normalized to the shared npm outcome enum server-side. */
|
|
364
|
+
reason: string;
|
|
365
|
+
/** Raw registry host; the server buckets it to public_npm | private | unknown. */
|
|
366
|
+
registryHost?: string;
|
|
367
|
+
/** Requested package names; the server sanitizes each per P6.1 and caps the array. */
|
|
368
|
+
packages: string[];
|
|
369
|
+
/** HTTP status from the failed registry fetch, when known. */
|
|
370
|
+
httpStatus?: number;
|
|
371
|
+
/** Underlying npm/pnpm error code (e.g. E404), when known. Server caps length. */
|
|
372
|
+
npmErrorCode?: string;
|
|
373
|
+
/**
|
|
374
|
+
* Which controlled install path produced the block. The server allowlists
|
|
375
|
+
* against `NPM_INSTALL_RUNNERS` and drops any other value.
|
|
376
|
+
*/
|
|
377
|
+
runner?: string;
|
|
378
|
+
/** Epoch ms when the block occurred (client clock). */
|
|
379
|
+
occurredAt: number;
|
|
380
|
+
// application attribution: NOT a wire field. The server derives it from the
|
|
381
|
+
// trusted scoped-JWT claim (`ctx.jwtClaims.app_id`) — a payload-controlled
|
|
382
|
+
// value would let any authenticated caller forge audit rows against another
|
|
383
|
+
// app in the same org.
|
|
384
|
+
}
|
|
@@ -22,10 +22,21 @@ const ENTERPRISE_LIKE_PLANS: ReadonlySet<BillingPlan> = new Set([
|
|
|
22
22
|
|
|
23
23
|
const TRIAL_LIKE_PLANS: ReadonlySet<BillingPlan> = new Set([BillingPlan.TRIAL, BillingPlan.FREE]);
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Plans entitled to the Policy Gates MVP. The MVP rollout is limited to
|
|
27
|
+
* enterprise (and POC) orgs, so this is intentionally narrower than
|
|
28
|
+
* {@link isEnterpriseLikePlan} (which also covers legacy PRO/STARTER).
|
|
29
|
+
*/
|
|
30
|
+
const POLICY_GATES_ENTITLED_PLANS: ReadonlySet<BillingPlan> = new Set([BillingPlan.ENTERPRISE, BillingPlan.POC]);
|
|
31
|
+
|
|
25
32
|
export function isEnterpriseLikePlan(plan: BillingPlan | undefined | null): boolean {
|
|
26
33
|
return plan != null && ENTERPRISE_LIKE_PLANS.has(plan);
|
|
27
34
|
}
|
|
28
35
|
|
|
36
|
+
export function isPolicyGatesEntitledPlan(plan: BillingPlan | undefined | null): boolean {
|
|
37
|
+
return plan != null && POLICY_GATES_ENTITLED_PLANS.has(plan);
|
|
38
|
+
}
|
|
39
|
+
|
|
29
40
|
export function isTrialLikePlan(plan: BillingPlan | undefined | null): boolean {
|
|
30
41
|
return plan != null && TRIAL_LIKE_PLANS.has(plan);
|
|
31
42
|
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spend Alerts — proactive billing alerts admins configure on /spending.
|
|
3
|
+
*
|
|
4
|
+
* Wire types shared between client (RTK Query slice in reduxApi/billing) and
|
|
5
|
+
* server (/v1/billing/spend-alerts controller). The DB stores `thresholds`
|
|
6
|
+
* and `recipients` as JSONB blobs whose shape matches these types exactly —
|
|
7
|
+
* see migration 1778896201000-create-spend-alert-table.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export type SpendAlertType = 'org_spend' | 'per_user_spend' | 'overage_spend' | 'refill_spend';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Unit identifier stored in `threshold.unit`. The client-side modal maps
|
|
14
|
+
* these to human labels (% of monthly usage / credits used / etc.); the
|
|
15
|
+
* server treats them opaquely for v1 (no evaluation yet).
|
|
16
|
+
*
|
|
17
|
+
* Adding a new unit requires an update here AND on the server-side enum
|
|
18
|
+
* in `validateThresholdUnit` so persistence rejects unknown values rather
|
|
19
|
+
* than silently storing them.
|
|
20
|
+
*/
|
|
21
|
+
export type SpendAlertThresholdUnit =
|
|
22
|
+
// Org spend
|
|
23
|
+
| 'percent'
|
|
24
|
+
| 'credits_used'
|
|
25
|
+
| 'dollars_spent'
|
|
26
|
+
// Per-user spend
|
|
27
|
+
| 'credits'
|
|
28
|
+
| 'dollars'
|
|
29
|
+
// Overage spend
|
|
30
|
+
| 'overage_credits'
|
|
31
|
+
| 'overage_dollars'
|
|
32
|
+
// Refill spend. Credit-denominated — every refill-eligible plan
|
|
33
|
+
// (TEAMS / POC) is credit-based, so there's no dollar variant.
|
|
34
|
+
| 'refill_credits';
|
|
35
|
+
|
|
36
|
+
export interface SpendAlertThreshold {
|
|
37
|
+
/** Positive number. Server validates this is > 0. */
|
|
38
|
+
value: number;
|
|
39
|
+
unit: SpendAlertThresholdUnit;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type SpendAlertRecipientKind =
|
|
43
|
+
/** Everyone with admin role on the org. Resolved at dispatch time. */
|
|
44
|
+
| 'all_admins'
|
|
45
|
+
/**
|
|
46
|
+
* Per-user alerts only. The user whose usage crossed the threshold.
|
|
47
|
+
* Resolved at dispatch time — not stored as a user_id, since the
|
|
48
|
+
* recipient depends on which user fired the alert.
|
|
49
|
+
*/
|
|
50
|
+
| 'triggering_user'
|
|
51
|
+
/** Specific user by id. Resolved against the user table at dispatch. */
|
|
52
|
+
| 'user';
|
|
53
|
+
|
|
54
|
+
export interface SpendAlertRecipient {
|
|
55
|
+
kind: SpendAlertRecipientKind;
|
|
56
|
+
/** Required when kind === 'user'. Ignored for other kinds. */
|
|
57
|
+
userId?: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface SpendAlertDto {
|
|
61
|
+
id: string;
|
|
62
|
+
organizationId: string;
|
|
63
|
+
alertType: SpendAlertType;
|
|
64
|
+
thresholds: SpendAlertThreshold[];
|
|
65
|
+
recipients: SpendAlertRecipient[];
|
|
66
|
+
created: string;
|
|
67
|
+
updated: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface CreateSpendAlertBody {
|
|
71
|
+
alertType: SpendAlertType;
|
|
72
|
+
thresholds: SpendAlertThreshold[];
|
|
73
|
+
recipients: SpendAlertRecipient[];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export type UpdateSpendAlertBody = Partial<Pick<CreateSpendAlertBody, 'thresholds' | 'recipients'>>;
|
|
77
|
+
|
|
78
|
+
export interface ListSpendAlertsResponseBody {
|
|
79
|
+
alerts: SpendAlertDto[];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface SpendAlertResponseBody {
|
|
83
|
+
alert: SpendAlertDto;
|
|
84
|
+
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// Single source of truth for the built-in security scan surfaces; flip to `true` to restore the security-scan UI and execution.
|
|
2
|
+
export const SECURITY_SCANS_ENABLED: boolean = false;
|
|
3
|
+
|
|
1
4
|
export type PolicyGateReadinessAction =
|
|
2
5
|
| 'contact_admin'
|
|
3
6
|
| 'fix_with_clark'
|
|
@@ -16,7 +19,11 @@ export type PolicyGateReadinessFindingSummary = {
|
|
|
16
19
|
|
|
17
20
|
export type PolicyGateReadinessFinding = {
|
|
18
21
|
blocking: boolean;
|
|
22
|
+
humanSummary?: string | null;
|
|
23
|
+
locationsJson?: unknown[];
|
|
24
|
+
remediationHintJson?: Record<string, unknown>;
|
|
19
25
|
severity: 'critical' | 'high' | 'info' | 'low' | 'medium';
|
|
26
|
+
technicalSummary?: string | null;
|
|
20
27
|
title: string;
|
|
21
28
|
};
|
|
22
29
|
|
|
@@ -48,10 +55,24 @@ export type PolicyGateReadinessItem = {
|
|
|
48
55
|
policyVersionId: string;
|
|
49
56
|
progress?: PolicyGateScanProgress;
|
|
50
57
|
reviewRunId?: string;
|
|
58
|
+
runs?: PolicyGateReadinessRun[];
|
|
51
59
|
staleReason?: string;
|
|
52
60
|
status: PolicyGateReadinessItemStatus;
|
|
53
61
|
};
|
|
54
62
|
|
|
63
|
+
export type PolicyGateReadinessRun = {
|
|
64
|
+
completedAt?: string;
|
|
65
|
+
createdAt?: string;
|
|
66
|
+
decision: 'advisory_allowed' | 'allowed' | 'blocked' | 'error_blocked' | 'not_applicable' | null;
|
|
67
|
+
errorCode?: string;
|
|
68
|
+
errorMessage?: string;
|
|
69
|
+
findingSummary: PolicyGateReadinessFindingSummary;
|
|
70
|
+
reviewRunId: string;
|
|
71
|
+
startedAt?: string;
|
|
72
|
+
staleReason?: string | null;
|
|
73
|
+
status: PolicyGateReadinessItemStatus;
|
|
74
|
+
};
|
|
75
|
+
|
|
55
76
|
export type PolicyGateReadinessItemStatus =
|
|
56
77
|
| 'advisory_findings'
|
|
57
78
|
| 'approval_required'
|
|
@@ -75,3 +96,10 @@ export type PolicyGateReadinessTarget = {
|
|
|
75
96
|
commitId: string;
|
|
76
97
|
directoryContentsHash: string | null;
|
|
77
98
|
};
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Stable error code used in BadRequestError messages when a deploy is rejected
|
|
102
|
+
* due to unresolved policy gate findings. Both server and client reference this
|
|
103
|
+
* constant so the contract doesn't rely on fragile string matching.
|
|
104
|
+
*/
|
|
105
|
+
export const POLICY_GATE_BLOCKED_ERROR = 'POLICY_GATE_BLOCKED';
|
package/src/types/rbac/index.ts
CHANGED
|
@@ -146,6 +146,7 @@ export enum ResourceTypeEnum {
|
|
|
146
146
|
INTEGRATIONS_DEFAULT_AI = 'integrations.default_ai',
|
|
147
147
|
LOGS = 'logs',
|
|
148
148
|
LOGS_STREAMS = 'logs.streams',
|
|
149
|
+
NATIVE_DATABASES = 'native_databases',
|
|
149
150
|
NPM_REGISTRY = 'npm_registry',
|
|
150
151
|
ORGANIZATION = 'org',
|
|
151
152
|
// ORGANIZATION_REQUESTS = 'org.requests',
|
|
@@ -283,6 +284,9 @@ export const ActionTypeByResourceType = {
|
|
|
283
284
|
MANAGE: ActionTypeEnum.MANAGE,
|
|
284
285
|
READ: ActionTypeEnum.READ
|
|
285
286
|
},
|
|
287
|
+
NATIVE_DATABASES: {
|
|
288
|
+
MANAGE: ActionTypeEnum.MANAGE
|
|
289
|
+
},
|
|
286
290
|
NPM_REGISTRY: {
|
|
287
291
|
MANAGE: ActionTypeEnum.MANAGE
|
|
288
292
|
},
|
|
@@ -86,6 +86,7 @@ export interface ReviewPolicyDto {
|
|
|
86
86
|
mode: ReviewPolicyMode;
|
|
87
87
|
scope: { type: ReviewPolicyScopeType };
|
|
88
88
|
lastRun: ReviewPolicyLastRunDto | null;
|
|
89
|
+
freshPendingApprovalRunCount: number;
|
|
89
90
|
createdBy: string | null;
|
|
90
91
|
created: string;
|
|
91
92
|
}
|
|
@@ -105,6 +106,7 @@ export interface ReviewPolicyRunDto {
|
|
|
105
106
|
status: ReviewRunStatus;
|
|
106
107
|
decision: ReviewRunDecision | null;
|
|
107
108
|
decisionReason: string | null;
|
|
109
|
+
hasFreshPendingApproval: boolean;
|
|
108
110
|
startedAt: string | null;
|
|
109
111
|
completedAt: string | null;
|
|
110
112
|
created: string;
|
|
@@ -146,11 +148,19 @@ export interface ReviewPolicyRunsDto {
|
|
|
146
148
|
runs: ReviewPolicyRunDto[];
|
|
147
149
|
}
|
|
148
150
|
|
|
151
|
+
// Trailing-time windows the summary can be scoped to. Order is semantically
|
|
152
|
+
// meaningful (shortest to longest) for rendering the selector.
|
|
153
|
+
export const REVIEW_POLICY_SUMMARY_WINDOWS = ['24h', '7d', '30d'] as const;
|
|
154
|
+
export type ReviewPolicySummaryWindow = (typeof REVIEW_POLICY_SUMMARY_WINDOWS)[number];
|
|
155
|
+
export const DEFAULT_REVIEW_POLICY_SUMMARY_WINDOW: ReviewPolicySummaryWindow = '24h';
|
|
156
|
+
|
|
149
157
|
export interface ReviewPolicySummaryDto {
|
|
158
|
+
// `activeAgents` is a point-in-time count and is not affected by `window`.
|
|
150
159
|
activeAgents: number;
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
160
|
+
agentRuns: number;
|
|
161
|
+
securityScans: number;
|
|
162
|
+
findings: number;
|
|
163
|
+
window: ReviewPolicySummaryWindow;
|
|
154
164
|
}
|
|
155
165
|
|
|
156
166
|
export type CreateReviewPolicyBody =
|