@company-semantics/contracts 1.15.0 → 1.16.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/package.json +1 -1
- package/src/api/generated-spec-hash.ts +2 -2
- package/src/api/generated.ts +80 -66
- package/src/dispatch/index.ts +99 -0
- package/src/index.ts +16 -0
package/package.json
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// AUTO-GENERATED — do not edit. Run pnpm generate:spec-hash to regenerate.
|
|
2
|
-
export const SPEC_HASH = '
|
|
3
|
-
export const SPEC_HASH_FULL = '
|
|
2
|
+
export const SPEC_HASH = 'e337542ea39d' as const;
|
|
3
|
+
export const SPEC_HASH_FULL = 'e337542ea39de6f11b03f87d300e3e4c842825267c6918b1a37f2f86502124f8' as const;
|
package/src/api/generated.ts
CHANGED
|
@@ -647,38 +647,38 @@ export interface paths {
|
|
|
647
647
|
patch?: never;
|
|
648
648
|
trace?: never;
|
|
649
649
|
};
|
|
650
|
-
"/api/
|
|
650
|
+
"/api/workspace/members/{id}/role": {
|
|
651
651
|
parameters: {
|
|
652
652
|
query?: never;
|
|
653
653
|
header?: never;
|
|
654
654
|
path?: never;
|
|
655
655
|
cookie?: never;
|
|
656
656
|
};
|
|
657
|
-
|
|
658
|
-
get: operations["getRbacRoles"];
|
|
657
|
+
get?: never;
|
|
659
658
|
put?: never;
|
|
660
659
|
post?: never;
|
|
661
660
|
delete?: never;
|
|
662
661
|
options?: never;
|
|
663
662
|
head?: never;
|
|
664
|
-
|
|
663
|
+
/** Change member role */
|
|
664
|
+
patch: operations["changeMemberRole"];
|
|
665
665
|
trace?: never;
|
|
666
666
|
};
|
|
667
|
-
"/api/
|
|
667
|
+
"/api/rbac/roles": {
|
|
668
668
|
parameters: {
|
|
669
669
|
query?: never;
|
|
670
670
|
header?: never;
|
|
671
671
|
path?: never;
|
|
672
672
|
cookie?: never;
|
|
673
673
|
};
|
|
674
|
-
|
|
674
|
+
/** List RBAC roles catalog (system + custom) with scopes and member counts */
|
|
675
|
+
get: operations["getRbacRoles"];
|
|
675
676
|
put?: never;
|
|
676
677
|
post?: never;
|
|
677
678
|
delete?: never;
|
|
678
679
|
options?: never;
|
|
679
680
|
head?: never;
|
|
680
|
-
|
|
681
|
-
patch: operations["changeMemberRole"];
|
|
681
|
+
patch?: never;
|
|
682
682
|
trace?: never;
|
|
683
683
|
};
|
|
684
684
|
"/api/user/orgs": {
|
|
@@ -2355,49 +2355,26 @@ export interface components {
|
|
|
2355
2355
|
WorkspaceHandleRequest: {
|
|
2356
2356
|
handle: string;
|
|
2357
2357
|
};
|
|
2358
|
-
WorkspaceMemberUnitSummary: {
|
|
2359
|
-
unitId: string;
|
|
2360
|
-
unitName: string;
|
|
2361
|
-
unitPath: string;
|
|
2362
|
-
/** @enum {string} */
|
|
2363
|
-
role: "owner" | "manager" | "member";
|
|
2364
|
-
};
|
|
2365
|
-
WorkspaceMember: {
|
|
2366
|
-
id: string;
|
|
2367
|
-
name: string;
|
|
2368
|
-
email: string;
|
|
2369
|
-
/** @enum {string} */
|
|
2370
|
-
role: "owner" | "admin" | "member" | "auditor";
|
|
2371
|
-
roleNames: string[];
|
|
2372
|
-
joinedAt: string;
|
|
2373
|
-
lastActiveAt: string | null;
|
|
2374
|
-
unitMemberships: components["schemas"]["WorkspaceMemberUnitSummary"][];
|
|
2375
|
-
unitMembershipsTruncated: boolean;
|
|
2376
|
-
inviteStatus: ("active" | "pending" | "expired") | null;
|
|
2377
|
-
};
|
|
2378
|
-
MemberRecentAction: {
|
|
2379
|
-
id: string;
|
|
2380
|
-
timestamp: string;
|
|
2381
|
-
action: string;
|
|
2382
|
-
summary: string;
|
|
2383
|
-
};
|
|
2384
|
-
WorkspaceMemberDetail: components["schemas"]["WorkspaceMember"] & {
|
|
2385
|
-
effectiveScopes: string[];
|
|
2386
|
-
recentActions: components["schemas"]["MemberRecentAction"][];
|
|
2387
|
-
};
|
|
2388
|
-
RoleCatalogEntry: {
|
|
2389
|
-
name: string;
|
|
2390
|
-
/** @enum {string} */
|
|
2391
|
-
type: "system" | "custom";
|
|
2392
|
-
description: string;
|
|
2393
|
-
scopes: string[];
|
|
2394
|
-
memberCount: number;
|
|
2395
|
-
};
|
|
2396
|
-
RoleCatalogResponse: {
|
|
2397
|
-
roles: components["schemas"]["RoleCatalogEntry"][];
|
|
2398
|
-
};
|
|
2399
2358
|
WorkspaceMembersResponse: {
|
|
2400
|
-
items:
|
|
2359
|
+
items: {
|
|
2360
|
+
id: string;
|
|
2361
|
+
name: string;
|
|
2362
|
+
email: string;
|
|
2363
|
+
/** @enum {string} */
|
|
2364
|
+
role: "owner" | "admin" | "member" | "auditor";
|
|
2365
|
+
roleNames: string[];
|
|
2366
|
+
joinedAt: string;
|
|
2367
|
+
lastActiveAt: string | null;
|
|
2368
|
+
unitMemberships: {
|
|
2369
|
+
unitId: string;
|
|
2370
|
+
unitName: string;
|
|
2371
|
+
unitPath: string;
|
|
2372
|
+
/** @enum {string} */
|
|
2373
|
+
role: "owner" | "manager" | "member";
|
|
2374
|
+
}[];
|
|
2375
|
+
unitMembershipsTruncated: boolean;
|
|
2376
|
+
inviteStatus: ("active" | "pending" | "expired") | null;
|
|
2377
|
+
}[];
|
|
2401
2378
|
nextCursor: string | null;
|
|
2402
2379
|
hasMore: boolean;
|
|
2403
2380
|
};
|
|
@@ -2566,6 +2543,32 @@ export interface components {
|
|
|
2566
2543
|
/** @enum {string} */
|
|
2567
2544
|
errorCode?: "IDENTITY_CONFLICT" | "DOMAIN_MISMATCH" | "ISSUER_MISMATCH" | "CALLBACK_ERROR";
|
|
2568
2545
|
};
|
|
2546
|
+
WorkspaceMemberDetail: {
|
|
2547
|
+
id: string;
|
|
2548
|
+
name: string;
|
|
2549
|
+
email: string;
|
|
2550
|
+
/** @enum {string} */
|
|
2551
|
+
role: "owner" | "admin" | "member" | "auditor";
|
|
2552
|
+
roleNames: string[];
|
|
2553
|
+
joinedAt: string;
|
|
2554
|
+
lastActiveAt: string | null;
|
|
2555
|
+
unitMemberships: {
|
|
2556
|
+
unitId: string;
|
|
2557
|
+
unitName: string;
|
|
2558
|
+
unitPath: string;
|
|
2559
|
+
/** @enum {string} */
|
|
2560
|
+
role: "owner" | "manager" | "member";
|
|
2561
|
+
}[];
|
|
2562
|
+
unitMembershipsTruncated: boolean;
|
|
2563
|
+
inviteStatus: ("active" | "pending" | "expired") | null;
|
|
2564
|
+
effectiveScopes: string[];
|
|
2565
|
+
recentActions: {
|
|
2566
|
+
id: string;
|
|
2567
|
+
timestamp: string;
|
|
2568
|
+
action: string;
|
|
2569
|
+
summary: string;
|
|
2570
|
+
}[];
|
|
2571
|
+
};
|
|
2569
2572
|
RemoveMemberResponse: {
|
|
2570
2573
|
success: boolean;
|
|
2571
2574
|
memberId: string;
|
|
@@ -2584,6 +2587,16 @@ export interface components {
|
|
|
2584
2587
|
/** @enum {string} */
|
|
2585
2588
|
newRole: "admin" | "member";
|
|
2586
2589
|
};
|
|
2590
|
+
RoleCatalogResponse: {
|
|
2591
|
+
roles: {
|
|
2592
|
+
name: string;
|
|
2593
|
+
/** @enum {string} */
|
|
2594
|
+
type: "system" | "custom";
|
|
2595
|
+
description: string;
|
|
2596
|
+
scopes: string[];
|
|
2597
|
+
memberCount: number;
|
|
2598
|
+
}[];
|
|
2599
|
+
};
|
|
2587
2600
|
UserOrgsResponse: {
|
|
2588
2601
|
orgs: {
|
|
2589
2602
|
userId: string;
|
|
@@ -2802,6 +2815,7 @@ export interface components {
|
|
|
2802
2815
|
target: {
|
|
2803
2816
|
type: string;
|
|
2804
2817
|
workspaceId?: string;
|
|
2818
|
+
service?: string;
|
|
2805
2819
|
};
|
|
2806
2820
|
connectionId?: string;
|
|
2807
2821
|
returnUrl?: string;
|
|
@@ -4467,48 +4481,48 @@ export interface operations {
|
|
|
4467
4481
|
};
|
|
4468
4482
|
};
|
|
4469
4483
|
};
|
|
4470
|
-
|
|
4484
|
+
changeMemberRole: {
|
|
4471
4485
|
parameters: {
|
|
4472
4486
|
query?: never;
|
|
4473
4487
|
header?: never;
|
|
4474
|
-
path
|
|
4488
|
+
path: {
|
|
4489
|
+
id: string;
|
|
4490
|
+
};
|
|
4475
4491
|
cookie?: never;
|
|
4476
4492
|
};
|
|
4477
|
-
requestBody
|
|
4493
|
+
requestBody: {
|
|
4494
|
+
content: {
|
|
4495
|
+
"application/json": components["schemas"]["ChangeMemberRoleRequest"];
|
|
4496
|
+
};
|
|
4497
|
+
};
|
|
4478
4498
|
responses: {
|
|
4479
|
-
/** @description Role
|
|
4499
|
+
/** @description Role changed successfully */
|
|
4480
4500
|
200: {
|
|
4481
4501
|
headers: {
|
|
4482
4502
|
[name: string]: unknown;
|
|
4483
4503
|
};
|
|
4484
4504
|
content: {
|
|
4485
|
-
"application/json": components["schemas"]["
|
|
4505
|
+
"application/json": components["schemas"]["ChangeMemberRoleResponse"];
|
|
4486
4506
|
};
|
|
4487
4507
|
};
|
|
4488
4508
|
};
|
|
4489
4509
|
};
|
|
4490
|
-
|
|
4510
|
+
getRbacRoles: {
|
|
4491
4511
|
parameters: {
|
|
4492
4512
|
query?: never;
|
|
4493
4513
|
header?: never;
|
|
4494
|
-
path
|
|
4495
|
-
id: string;
|
|
4496
|
-
};
|
|
4514
|
+
path?: never;
|
|
4497
4515
|
cookie?: never;
|
|
4498
4516
|
};
|
|
4499
|
-
requestBody
|
|
4500
|
-
content: {
|
|
4501
|
-
"application/json": components["schemas"]["ChangeMemberRoleRequest"];
|
|
4502
|
-
};
|
|
4503
|
-
};
|
|
4517
|
+
requestBody?: never;
|
|
4504
4518
|
responses: {
|
|
4505
|
-
/** @description Role
|
|
4519
|
+
/** @description Role catalog */
|
|
4506
4520
|
200: {
|
|
4507
4521
|
headers: {
|
|
4508
4522
|
[name: string]: unknown;
|
|
4509
4523
|
};
|
|
4510
4524
|
content: {
|
|
4511
|
-
"application/json": components["schemas"]["
|
|
4525
|
+
"application/json": components["schemas"]["RoleCatalogResponse"];
|
|
4512
4526
|
};
|
|
4513
4527
|
};
|
|
4514
4528
|
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dispatch-deny vocabulary.
|
|
3
|
+
*
|
|
4
|
+
* The four deny paths on the agent-action dispatch flow — consent missing,
|
|
5
|
+
* write-tier disabled, per-provider kill switch, and execution-budget
|
|
6
|
+
* exhausted — all return the canonical `ErrorResponse` envelope with one of
|
|
7
|
+
* the codes defined below plus a per-code `meta` payload. The shapes are
|
|
8
|
+
* shared between the backend (which emits) and the app (which renders a
|
|
9
|
+
* recovery affordance), so they live in contracts per the promotion rule.
|
|
10
|
+
*
|
|
11
|
+
* HTTP status is carried by the envelope, not duplicated here; conventional
|
|
12
|
+
* mapping in the backend:
|
|
13
|
+
* - `incremental_consent_required` → 402 (grant required to proceed)
|
|
14
|
+
* - `write_tier_disabled` → 403
|
|
15
|
+
* - `provider_access_denied` → 403
|
|
16
|
+
* - `execution_budget_exceeded` → 429
|
|
17
|
+
*
|
|
18
|
+
* @see ../errors/index.ts for the `ErrorResponse` envelope.
|
|
19
|
+
* @see PRD-00519/00521/00522 — the PRDs that introduced these denies.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
export const DISPATCH_DENY_CODES = [
|
|
23
|
+
'incremental_consent_required',
|
|
24
|
+
'write_tier_disabled',
|
|
25
|
+
'provider_access_denied',
|
|
26
|
+
'execution_budget_exceeded',
|
|
27
|
+
] as const;
|
|
28
|
+
|
|
29
|
+
export type DispatchDenyCode = (typeof DISPATCH_DENY_CODES)[number];
|
|
30
|
+
|
|
31
|
+
export type ActionTier = 'SAFE' | 'EXTERNAL' | 'DESTRUCTIVE';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The user has no active grant row in `incremental_consents` for the
|
|
35
|
+
* `(user_id, org_id, action_id)` triple. Recoverable by the user: they
|
|
36
|
+
* POST `grantPath` to create the grant, then retry the original action.
|
|
37
|
+
*/
|
|
38
|
+
export interface IncrementalConsentRequiredMeta {
|
|
39
|
+
actionId: string;
|
|
40
|
+
tier: ActionTier;
|
|
41
|
+
requiredScopes: string[];
|
|
42
|
+
/** HTTP path the app can POST to with `{ actionId }` to create the grant. */
|
|
43
|
+
grantPath: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The global `WRITE_TIER_ENABLED[tier]` kill switch is off. Recoverable
|
|
48
|
+
* only by an operator flipping the config — not user-actionable.
|
|
49
|
+
*/
|
|
50
|
+
export interface WriteTierDisabledMeta {
|
|
51
|
+
actionId: string;
|
|
52
|
+
tier: ActionTier;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Distinct reasons `ProviderAccessGate.canDispatchAction` can deny.
|
|
57
|
+
* Kept separate from the global `WRITE_TIER_ENABLED` codes so the app
|
|
58
|
+
* can phrase the message by cause (provider paused vs. org override vs.
|
|
59
|
+
* tier paused for this provider).
|
|
60
|
+
*/
|
|
61
|
+
export type ProviderAccessDenyReason =
|
|
62
|
+
| 'provider-disabled'
|
|
63
|
+
| 'org-override'
|
|
64
|
+
| 'tier-SAFE-disabled'
|
|
65
|
+
| 'tier-EXTERNAL-disabled'
|
|
66
|
+
| 'tier-DESTRUCTIVE-disabled'
|
|
67
|
+
| 'write-tier-SAFE-globally-disabled'
|
|
68
|
+
| 'write-tier-EXTERNAL-globally-disabled'
|
|
69
|
+
| 'write-tier-DESTRUCTIVE-globally-disabled';
|
|
70
|
+
|
|
71
|
+
export interface ProviderAccessDeniedMeta {
|
|
72
|
+
reason: ProviderAccessDenyReason;
|
|
73
|
+
provider: string;
|
|
74
|
+
tier: ActionTier;
|
|
75
|
+
actionType: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The signed execution has hit one of its atomic per-run caps. `kind` tells
|
|
80
|
+
* the app which cap tripped so it can phrase the message correctly; the
|
|
81
|
+
* recovery is always "start a new session / execution".
|
|
82
|
+
*/
|
|
83
|
+
export interface ExecutionBudgetExceededMeta {
|
|
84
|
+
kind: 'token_uses' | 'time_window' | 'provider_calls' | 'rows_returned';
|
|
85
|
+
executionId: string;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Type-level map: deny code → meta shape. Drives the app's deny renderer. */
|
|
89
|
+
export interface DispatchDenyMetaByCode {
|
|
90
|
+
incremental_consent_required: IncrementalConsentRequiredMeta;
|
|
91
|
+
write_tier_disabled: WriteTierDisabledMeta;
|
|
92
|
+
provider_access_denied: ProviderAccessDeniedMeta;
|
|
93
|
+
execution_budget_exceeded: ExecutionBudgetExceededMeta;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Narrow `unknown` to a `DispatchDenyCode` for error-code dispatch switches. */
|
|
97
|
+
export function isDispatchDenyCode(code: unknown): code is DispatchDenyCode {
|
|
98
|
+
return typeof code === 'string' && (DISPATCH_DENY_CODES as readonly string[]).includes(code);
|
|
99
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -166,6 +166,22 @@ export type {
|
|
|
166
166
|
export type { AuthStartMode, AuthStartResponse } from './auth/index'
|
|
167
167
|
export { OTPErrorCode } from './auth/index'
|
|
168
168
|
|
|
169
|
+
// Dispatch deny vocabulary (PRD-00519/00521/00522)
|
|
170
|
+
export {
|
|
171
|
+
DISPATCH_DENY_CODES,
|
|
172
|
+
isDispatchDenyCode,
|
|
173
|
+
} from './dispatch/index'
|
|
174
|
+
export type {
|
|
175
|
+
ActionTier,
|
|
176
|
+
DispatchDenyCode,
|
|
177
|
+
DispatchDenyMetaByCode,
|
|
178
|
+
ExecutionBudgetExceededMeta,
|
|
179
|
+
IncrementalConsentRequiredMeta,
|
|
180
|
+
ProviderAccessDenyReason,
|
|
181
|
+
ProviderAccessDeniedMeta,
|
|
182
|
+
WriteTierDisabledMeta,
|
|
183
|
+
} from './dispatch/index'
|
|
184
|
+
|
|
169
185
|
// Email domain types
|
|
170
186
|
// @see ADR-CONT-034 for design rationale
|
|
171
187
|
export type {
|