borgmcp-shared 0.9.0 → 0.10.1
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/README.md +1 -2
- package/RELEASES.md +5 -0
- package/dist/conformance/adapter.d.ts +13 -4
- package/dist/conformance/adapter.d.ts.map +1 -1
- package/dist/conformance/adapter.js +205 -23
- package/dist/conformance/adapter.js.map +1 -1
- package/dist/conformance/index.d.ts +43 -0
- package/dist/conformance/index.d.ts.map +1 -1
- package/dist/conformance/index.js +91 -0
- package/dist/conformance/index.js.map +1 -1
- package/dist/protocol/contract.d.ts +18 -2
- package/dist/protocol/contract.d.ts.map +1 -1
- package/dist/protocol/contract.js +19 -3
- package/dist/protocol/contract.js.map +1 -1
- package/dist/protocol/coordination.d.ts +27 -0
- package/dist/protocol/coordination.d.ts.map +1 -1
- package/dist/protocol/coordination.js +71 -1
- package/dist/protocol/coordination.js.map +1 -1
- package/dist/protocol/errors.d.ts +5 -1
- package/dist/protocol/errors.d.ts.map +1 -1
- package/dist/protocol/errors.js +5 -1
- package/dist/protocol/errors.js.map +1 -1
- package/dist/protocol/version.d.ts +1 -1
- package/dist/protocol/version.js +1 -1
- package/docs/compatibility.md +9 -1
- package/docs/enrollment.md +2 -5
- package/docs/release-records.json +28 -0
- package/docs/releasing.md +5 -9
- package/package.json +1 -1
- package/src/conformance/adapter.ts +369 -32
- package/src/conformance/index.ts +139 -0
- package/src/protocol/contract.ts +20 -3
- package/src/protocol/coordination.ts +121 -0
- package/src/protocol/errors.ts +6 -3
- package/src/protocol/version.ts +2 -2
package/src/conformance/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
type InvitationArtifact,
|
|
13
13
|
} from '../protocol/contract.js';
|
|
14
14
|
import type { EnrichedStreamEntry } from '../protocol/types.js';
|
|
15
|
+
import { ROLE_IN_USE_DELETE_MESSAGE } from '../protocol/coordination.js';
|
|
15
16
|
|
|
16
17
|
export * from './adapter.js';
|
|
17
18
|
|
|
@@ -775,6 +776,144 @@ export interface RuntimeMetadataRepositoryConformanceVector {
|
|
|
775
776
|
expected: { working_repo_name: string; working_repo_origin: string } | null;
|
|
776
777
|
}
|
|
777
778
|
|
|
779
|
+
export interface RoleDeleteConformanceVector {
|
|
780
|
+
name: string;
|
|
781
|
+
fixture:
|
|
782
|
+
| 'deletable'
|
|
783
|
+
| 'evicted-drone'
|
|
784
|
+
| 'active-drone'
|
|
785
|
+
| 'default'
|
|
786
|
+
| 'mandatory'
|
|
787
|
+
| 'human-seat'
|
|
788
|
+
| 'taxonomy-reference'
|
|
789
|
+
| 'unknown';
|
|
790
|
+
expected:
|
|
791
|
+
| {
|
|
792
|
+
status: 200;
|
|
793
|
+
response: { deleted: true };
|
|
794
|
+
mutation: 'delete-role';
|
|
795
|
+
evicted_drone_retarget?: 'default-role';
|
|
796
|
+
activity_log_attribution?: 'preserved';
|
|
797
|
+
}
|
|
798
|
+
| {
|
|
799
|
+
status: 409;
|
|
800
|
+
error: 'ROLE_IN_USE' | 'DEFAULT_ROLE_REQUIRED' | 'ROLE_REQUIRED' | 'ROLE_REFERENCED';
|
|
801
|
+
mutation: 'none';
|
|
802
|
+
message?: typeof ROLE_IN_USE_DELETE_MESSAGE;
|
|
803
|
+
}
|
|
804
|
+
| { status: 404; error: 'NOT_FOUND'; mutation: 'none' };
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
/** Portable role-deletion outcomes, including every integrity refusal. */
|
|
808
|
+
export const ROLE_DELETE_CONFORMANCE: readonly RoleDeleteConformanceVector[] = [
|
|
809
|
+
{
|
|
810
|
+
name: 'deletes an unreferenced unassigned ordinary role',
|
|
811
|
+
fixture: 'deletable',
|
|
812
|
+
expected: { status: 200, response: { deleted: true }, mutation: 'delete-role' },
|
|
813
|
+
},
|
|
814
|
+
{
|
|
815
|
+
name: 'retargets evicted drones without losing existing log attribution',
|
|
816
|
+
fixture: 'evicted-drone',
|
|
817
|
+
expected: {
|
|
818
|
+
status: 200,
|
|
819
|
+
response: { deleted: true },
|
|
820
|
+
mutation: 'delete-role',
|
|
821
|
+
evicted_drone_retarget: 'default-role',
|
|
822
|
+
activity_log_attribution: 'preserved',
|
|
823
|
+
},
|
|
824
|
+
},
|
|
825
|
+
{
|
|
826
|
+
name: 'refuses a role held by an active drone with an actionable message',
|
|
827
|
+
fixture: 'active-drone',
|
|
828
|
+
expected: {
|
|
829
|
+
status: 409,
|
|
830
|
+
error: 'ROLE_IN_USE',
|
|
831
|
+
mutation: 'none',
|
|
832
|
+
message: ROLE_IN_USE_DELETE_MESSAGE,
|
|
833
|
+
},
|
|
834
|
+
},
|
|
835
|
+
{
|
|
836
|
+
name: 'refuses the cube default role',
|
|
837
|
+
fixture: 'default',
|
|
838
|
+
expected: { status: 409, error: 'DEFAULT_ROLE_REQUIRED', mutation: 'none' },
|
|
839
|
+
},
|
|
840
|
+
{
|
|
841
|
+
name: 'refuses a mandatory role',
|
|
842
|
+
fixture: 'mandatory',
|
|
843
|
+
expected: { status: 409, error: 'ROLE_REQUIRED', mutation: 'none' },
|
|
844
|
+
},
|
|
845
|
+
{
|
|
846
|
+
name: 'refuses a human-seat role',
|
|
847
|
+
fixture: 'human-seat',
|
|
848
|
+
expected: { status: 409, error: 'ROLE_REQUIRED', mutation: 'none' },
|
|
849
|
+
},
|
|
850
|
+
{
|
|
851
|
+
name: 'refuses a taxonomy default-recipient role',
|
|
852
|
+
fixture: 'taxonomy-reference',
|
|
853
|
+
expected: { status: 409, error: 'ROLE_REFERENCED', mutation: 'none' },
|
|
854
|
+
},
|
|
855
|
+
{
|
|
856
|
+
name: 'hides an unknown or inaccessible role',
|
|
857
|
+
fixture: 'unknown',
|
|
858
|
+
expected: { status: 404, error: 'NOT_FOUND', mutation: 'none' },
|
|
859
|
+
},
|
|
860
|
+
];
|
|
861
|
+
|
|
862
|
+
export interface RoleRationaleConformanceVector {
|
|
863
|
+
name: string;
|
|
864
|
+
fixture:
|
|
865
|
+
| 'uuid-exact'
|
|
866
|
+
| 'name-case-insensitive'
|
|
867
|
+
| 'unknown-role'
|
|
868
|
+
| 'inaccessible-role'
|
|
869
|
+
| 'unknown-section'
|
|
870
|
+
| 'ambiguous-role-name'
|
|
871
|
+
| 'invalid-selector';
|
|
872
|
+
expected:
|
|
873
|
+
| { status: 200; canonical_heading: true; exact_body: true; mutation: 'none' }
|
|
874
|
+
| { status: 404; error: 'ROLE_NOT_FOUND' | 'ROLE_SECTION_NOT_FOUND'; mutation: 'none' }
|
|
875
|
+
| { status: 400; error: 'INVALID_INPUT'; mutation: 'none' };
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
/** Portable role-rationale lookup outcomes for the named-section route. */
|
|
879
|
+
export const ROLE_RATIONALE_CONFORMANCE: readonly RoleRationaleConformanceVector[] = [
|
|
880
|
+
{
|
|
881
|
+
name: 'resolves an exact role UUID and returns the exact stored section',
|
|
882
|
+
fixture: 'uuid-exact',
|
|
883
|
+
expected: { status: 200, canonical_heading: true, exact_body: true, mutation: 'none' },
|
|
884
|
+
},
|
|
885
|
+
{
|
|
886
|
+
name: 'resolves a role name and section heading case-insensitively',
|
|
887
|
+
fixture: 'name-case-insensitive',
|
|
888
|
+
expected: { status: 200, canonical_heading: true, exact_body: true, mutation: 'none' },
|
|
889
|
+
},
|
|
890
|
+
{
|
|
891
|
+
name: 'returns a typed refusal for an unknown role',
|
|
892
|
+
fixture: 'unknown-role',
|
|
893
|
+
expected: { status: 404, error: 'ROLE_NOT_FOUND', mutation: 'none' },
|
|
894
|
+
},
|
|
895
|
+
{
|
|
896
|
+
name: 'does not resolve a role outside the addressed cube',
|
|
897
|
+
fixture: 'inaccessible-role',
|
|
898
|
+
expected: { status: 404, error: 'ROLE_NOT_FOUND', mutation: 'none' },
|
|
899
|
+
},
|
|
900
|
+
{
|
|
901
|
+
name: 'returns a typed refusal for an unknown section',
|
|
902
|
+
fixture: 'unknown-section',
|
|
903
|
+
expected: { status: 404, error: 'ROLE_SECTION_NOT_FOUND', mutation: 'none' },
|
|
904
|
+
},
|
|
905
|
+
{
|
|
906
|
+
name: 'rejects a role name with multiple case-insensitive matches',
|
|
907
|
+
fixture: 'ambiguous-role-name',
|
|
908
|
+
expected: { status: 400, error: 'INVALID_INPUT', mutation: 'none' },
|
|
909
|
+
},
|
|
910
|
+
{
|
|
911
|
+
name: 'rejects malformed or ambiguous selectors',
|
|
912
|
+
fixture: 'invalid-selector',
|
|
913
|
+
expected: { status: 400, error: 'INVALID_INPUT', mutation: 'none' },
|
|
914
|
+
},
|
|
915
|
+
];
|
|
916
|
+
|
|
778
917
|
/** One canonical corpus consumed unchanged by shared, server, and client tests. */
|
|
779
918
|
export const RUNTIME_METADATA_REPOSITORY_CONFORMANCE:
|
|
780
919
|
readonly RuntimeMetadataRepositoryConformanceVector[] = [
|
package/src/protocol/contract.ts
CHANGED
|
@@ -13,15 +13,19 @@ import type {
|
|
|
13
13
|
} from './types.js';
|
|
14
14
|
|
|
15
15
|
export const SHARED_PACKAGE_NAME = 'borgmcp-shared' as const;
|
|
16
|
-
export const SHARED_PACKAGE_VERSION = '0.
|
|
16
|
+
export const SHARED_PACKAGE_VERSION = '0.10.1' as const;
|
|
17
17
|
/** Maximum UTF-8 payload for each newly recorded decision text field. */
|
|
18
18
|
export const DECISION_TEXT_MAX_BYTES = 512 as const;
|
|
19
|
+
/** Maximum UTF-8 size of role detailed-description text and any returned section slice. */
|
|
20
|
+
export const ROLE_TEXT_MAX_BYTES = 51_200 as const;
|
|
19
21
|
|
|
20
22
|
export const HEALTH_PATH = '/healthz' as const;
|
|
21
23
|
export const PROTOCOL_INFO_PATH = '/api/protocol' as const;
|
|
22
24
|
export const ENROLLMENT_EXCHANGE_PATH = '/api/enrollment/exchange' as const;
|
|
23
25
|
export const CUBES_PATH = '/api/cubes' as const;
|
|
24
26
|
export const CUBE_PATH = '/api/cubes/:cubeId' as const;
|
|
27
|
+
export const ROLE_PATH = '/api/cubes/:cubeId/roles/:roleId' as const;
|
|
28
|
+
export const ROLE_RATIONALE_PATH = '/api/cubes/:cubeId/role-rationale' as const;
|
|
25
29
|
export const REPOSITORY_CUBE_RESOLVE_PATH = '/api/repository-cubes/resolve' as const;
|
|
26
30
|
export const REPOSITORY_CUBE_ASSOCIATION_PATH = '/api/repository-cubes/association' as const;
|
|
27
31
|
export const ATTACH_PATH = '/api/client/attach' as const;
|
|
@@ -39,6 +43,20 @@ export const PROTOCOL_HTTP_CONTRACT = {
|
|
|
39
43
|
success_status: 200,
|
|
40
44
|
mutation: true,
|
|
41
45
|
},
|
|
46
|
+
role_delete: {
|
|
47
|
+
method: 'DELETE',
|
|
48
|
+
path: ROLE_PATH,
|
|
49
|
+
authenticated: true,
|
|
50
|
+
success_status: 200,
|
|
51
|
+
mutation: true,
|
|
52
|
+
},
|
|
53
|
+
role_rationale: {
|
|
54
|
+
method: 'POST',
|
|
55
|
+
path: ROLE_RATIONALE_PATH,
|
|
56
|
+
authenticated: true,
|
|
57
|
+
success_status: 200,
|
|
58
|
+
mutation: false,
|
|
59
|
+
},
|
|
42
60
|
repository_cube_resolve: {
|
|
43
61
|
method: 'POST',
|
|
44
62
|
path: REPOSITORY_CUBE_RESOLVE_PATH,
|
|
@@ -74,7 +92,6 @@ export const PROTOCOL_HTTP_CONTRACT = {
|
|
|
74
92
|
},
|
|
75
93
|
auth_missing_status: 401,
|
|
76
94
|
auth_invalid_status: 401,
|
|
77
|
-
auth_expired_status: 401,
|
|
78
95
|
session_revoked_status: 401,
|
|
79
96
|
session_rejected_status: 401,
|
|
80
97
|
cursor_expired_status: 410,
|
|
@@ -563,7 +580,7 @@ export function decodeProtocolTagPreflight(value: unknown): ProtocolTagPreflight
|
|
|
563
580
|
exactKeys(input, ['protocol_version'], ['protocol_version']);
|
|
564
581
|
if (input.protocol_version !== PROTOCOL_VERSION) {
|
|
565
582
|
throw new ProtocolContractError(
|
|
566
|
-
'This client requires protocol
|
|
583
|
+
'This client requires protocol v8. The peer presents a different version. Update `borgmcp-server` and `borgmcp` to matching releases — server first, then client.',
|
|
567
584
|
ErrorCode.UNSUPPORTED_PROTOCOL_VERSION,
|
|
568
585
|
['protocol_version'],
|
|
569
586
|
);
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
decodeLogCursor,
|
|
6
6
|
decodeProtocolEnvelope,
|
|
7
7
|
decodeUuid,
|
|
8
|
+
ROLE_TEXT_MAX_BYTES,
|
|
8
9
|
utf8ByteLength,
|
|
9
10
|
type LogCursor,
|
|
10
11
|
type ProtocolEnvelope,
|
|
@@ -16,6 +17,7 @@ import type {
|
|
|
16
17
|
EnrichedStreamEntry,
|
|
17
18
|
RoutingEcho,
|
|
18
19
|
} from './types.js';
|
|
20
|
+
import { isLabelLine, parseRoleSections } from '../role-section.js';
|
|
19
21
|
|
|
20
22
|
export interface ReadLogRequest {
|
|
21
23
|
cursor: LogCursor | null;
|
|
@@ -65,6 +67,34 @@ export interface EvictDroneResult {
|
|
|
65
67
|
evicted: true;
|
|
66
68
|
}
|
|
67
69
|
|
|
70
|
+
export type DeleteRoleRequest = Record<string, never>;
|
|
71
|
+
|
|
72
|
+
export const ROLE_IN_USE_DELETE_MESSAGE =
|
|
73
|
+
'Reassign or evict every drone assigned to this role before deleting it.' as const;
|
|
74
|
+
|
|
75
|
+
export interface DeleteRoleResult {
|
|
76
|
+
role_id: string;
|
|
77
|
+
deleted: true;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface RoleRationaleRequest {
|
|
81
|
+
role: string;
|
|
82
|
+
section: string;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface RoleRationaleResult {
|
|
86
|
+
role_id: string;
|
|
87
|
+
role_name: string;
|
|
88
|
+
section: {
|
|
89
|
+
heading: string;
|
|
90
|
+
body: string;
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Maximum UTF-8 payload for one returned role-description section. */
|
|
95
|
+
export const ROLE_RATIONALE_SECTION_BODY_MAX_BYTES =
|
|
96
|
+
ROLE_TEXT_MAX_BYTES;
|
|
97
|
+
|
|
68
98
|
function object(value: unknown): Record<string, unknown> {
|
|
69
99
|
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
70
100
|
throw new ProtocolContractError('Expected a coordination object.');
|
|
@@ -171,6 +201,97 @@ export function decodeEvictDroneResultEnvelope(
|
|
|
171
201
|
return decodeProtocolEnvelope(value, decodeEvictDroneResult);
|
|
172
202
|
}
|
|
173
203
|
|
|
204
|
+
export function decodeDeleteRoleRequest(value: unknown): DeleteRoleRequest {
|
|
205
|
+
const input = object(value);
|
|
206
|
+
exact(input, [], []);
|
|
207
|
+
return {};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function decodeDeleteRoleRequestEnvelope(
|
|
211
|
+
value: unknown,
|
|
212
|
+
): ProtocolEnvelope<DeleteRoleRequest> {
|
|
213
|
+
return decodeProtocolEnvelope(value, decodeDeleteRoleRequest);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export function decodeDeleteRoleResult(value: unknown): DeleteRoleResult {
|
|
217
|
+
const input = object(value);
|
|
218
|
+
exact(input, ['role_id', 'deleted'], ['role_id', 'deleted']);
|
|
219
|
+
if (input.deleted !== true) throw new ProtocolContractError('Invalid role deletion result.');
|
|
220
|
+
return { role_id: decodeUuid(input.role_id, ['role_id']), deleted: true };
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function decodeDeleteRoleResultEnvelope(
|
|
224
|
+
value: unknown,
|
|
225
|
+
): ProtocolEnvelope<DeleteRoleResult> {
|
|
226
|
+
return decodeProtocolEnvelope(value, decodeDeleteRoleResult);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function plainRoleSectionHeading(value: unknown): string {
|
|
230
|
+
const heading = boundedString(value, 'section', 60);
|
|
231
|
+
if (
|
|
232
|
+
heading !== heading.trim() ||
|
|
233
|
+
/[\u0000-\u001f\u007f-\u009f]/.test(heading) ||
|
|
234
|
+
!isLabelLine(`${heading}:`)
|
|
235
|
+
) {
|
|
236
|
+
throw new ProtocolContractError('Invalid coordination field "section".');
|
|
237
|
+
}
|
|
238
|
+
return heading;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export function decodeRoleRationaleRequest(value: unknown): RoleRationaleRequest {
|
|
242
|
+
const input = object(value);
|
|
243
|
+
exact(input, ['role', 'section'], ['role', 'section']);
|
|
244
|
+
const role = boundedString(input.role, 'role', 120);
|
|
245
|
+
if (role !== role.trim() || /[\u0000-\u001f\u007f-\u009f]/.test(role)) {
|
|
246
|
+
throw new ProtocolContractError('Invalid coordination field "role".');
|
|
247
|
+
}
|
|
248
|
+
return { role, section: plainRoleSectionHeading(input.section) };
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export function decodeRoleRationaleRequestEnvelope(
|
|
252
|
+
value: unknown,
|
|
253
|
+
): ProtocolEnvelope<RoleRationaleRequest> {
|
|
254
|
+
return decodeProtocolEnvelope(value, decodeRoleRationaleRequest);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export function decodeRoleRationaleResult(value: unknown): RoleRationaleResult {
|
|
258
|
+
const input = object(value);
|
|
259
|
+
exact(input, ['role_id', 'role_name', 'section'], ['role_id', 'role_name', 'section']);
|
|
260
|
+
const section = object(input.section);
|
|
261
|
+
exact(section, ['heading', 'body'], ['heading', 'body']);
|
|
262
|
+
const heading = plainRoleSectionHeading(section.heading);
|
|
263
|
+
const body = boundedString(
|
|
264
|
+
section.body,
|
|
265
|
+
'section.body',
|
|
266
|
+
ROLE_RATIONALE_SECTION_BODY_MAX_BYTES,
|
|
267
|
+
);
|
|
268
|
+
const parsed = parseRoleSections(body);
|
|
269
|
+
if (
|
|
270
|
+
parsed.length !== 2 ||
|
|
271
|
+
parsed[0]?.kind !== 'preamble' ||
|
|
272
|
+
parsed[0].body !== '' ||
|
|
273
|
+
parsed[1]?.kind !== 'label' ||
|
|
274
|
+
parsed[1].heading !== heading ||
|
|
275
|
+
parsed[1].body !== body
|
|
276
|
+
) {
|
|
277
|
+
throw new ProtocolContractError('Invalid coordination field "section.body".');
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
role_id: decodeUuid(input.role_id, ['role_id']),
|
|
281
|
+
role_name: boundedString(input.role_name, 'role_name', 120),
|
|
282
|
+
section: {
|
|
283
|
+
heading,
|
|
284
|
+
body,
|
|
285
|
+
},
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export function decodeRoleRationaleResultEnvelope(
|
|
290
|
+
value: unknown,
|
|
291
|
+
): ProtocolEnvelope<RoleRationaleResult> {
|
|
292
|
+
return decodeProtocolEnvelope(value, decodeRoleRationaleResult);
|
|
293
|
+
}
|
|
294
|
+
|
|
174
295
|
export function decodeReadLogRequest(value: unknown): ReadLogRequest {
|
|
175
296
|
const input = object(value);
|
|
176
297
|
exact(input, ['cursor', 'limit'], ['cursor']);
|
package/src/protocol/errors.ts
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
export enum ErrorCode {
|
|
3
3
|
AUTH_MISSING = 'AUTH_MISSING',
|
|
4
4
|
AUTH_INVALID = 'AUTH_INVALID',
|
|
5
|
-
AUTH_EXPIRED = 'AUTH_EXPIRED',
|
|
6
5
|
SUBSCRIPTION_REQUIRED = 'SUBSCRIPTION_REQUIRED',
|
|
7
6
|
ACCESS_DENIED = 'ACCESS_DENIED',
|
|
8
7
|
INVALID_INPUT = 'INVALID_INPUT',
|
|
@@ -16,6 +15,11 @@ export enum ErrorCode {
|
|
|
16
15
|
REPOSITORY_ALREADY_ASSOCIATED = 'REPOSITORY_ALREADY_ASSOCIATED',
|
|
17
16
|
CUBE_ALREADY_ASSOCIATED = 'CUBE_ALREADY_ASSOCIATED',
|
|
18
17
|
ROLE_IN_USE = 'ROLE_IN_USE',
|
|
18
|
+
DEFAULT_ROLE_REQUIRED = 'DEFAULT_ROLE_REQUIRED',
|
|
19
|
+
ROLE_REQUIRED = 'ROLE_REQUIRED',
|
|
20
|
+
ROLE_REFERENCED = 'ROLE_REFERENCED',
|
|
21
|
+
ROLE_NOT_FOUND = 'ROLE_NOT_FOUND',
|
|
22
|
+
ROLE_SECTION_NOT_FOUND = 'ROLE_SECTION_NOT_FOUND',
|
|
19
23
|
ROLE_HAS_FROZEN_DRONES = 'ROLE_HAS_FROZEN_DRONES',
|
|
20
24
|
CUBE_DELETED = 'CUBE_DELETED',
|
|
21
25
|
DRONE_EVICTED = 'DRONE_EVICTED',
|
|
@@ -28,8 +32,7 @@ export enum ErrorCode {
|
|
|
28
32
|
* The presented session bearer does not match the seat it targets: a fresh or
|
|
29
33
|
* non-matching bearer against an already-bound active seat. Distinct from
|
|
30
34
|
* SESSION_REVOKED (a formerly valid credential that was explicitly revoked).
|
|
31
|
-
*
|
|
32
|
-
* server's typed 401 takeover rejection.
|
|
35
|
+
* Carried by the server's typed 401 takeover rejection.
|
|
33
36
|
*/
|
|
34
37
|
SESSION_REJECTED = 'SESSION_REJECTED',
|
|
35
38
|
}
|
package/src/protocol/version.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Current Borg coordination protocol generation. Clean-slate
|
|
2
|
-
export const PROTOCOL_VERSION = '
|
|
1
|
+
/** Current Borg coordination protocol generation. Clean-slate v8. */
|
|
2
|
+
export const PROTOCOL_VERSION = '8' as const;
|
|
3
3
|
|
|
4
4
|
export type ProtocolVersion = typeof PROTOCOL_VERSION;
|