borgmcp-shared 1.1.0 → 2.0.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/README.md +12 -6
- package/dist/conformance/adapter.d.ts +0 -3
- package/dist/conformance/adapter.d.ts.map +1 -1
- package/dist/conformance/adapter.js +23 -42
- package/dist/conformance/adapter.js.map +1 -1
- package/dist/conformance/index.d.ts +3 -3
- package/dist/conformance/index.d.ts.map +1 -1
- package/dist/conformance/index.js +3 -10
- package/dist/conformance/index.js.map +1 -1
- package/dist/protocol/contract.d.ts +1 -1
- package/dist/protocol/contract.js +1 -1
- package/dist/protocol/coordination.d.ts +0 -9
- package/dist/protocol/coordination.d.ts.map +1 -1
- package/dist/protocol/coordination.js +1 -33
- package/dist/protocol/coordination.js.map +1 -1
- package/dist/protocol/types.d.ts +0 -9
- package/dist/protocol/types.d.ts.map +1 -1
- package/dist/protocol/version.d.ts +1 -1
- package/dist/protocol/version.js +1 -1
- package/docs/compatibility.md +8 -3
- package/docs/releases/1.2.0.md +20 -0
- package/docs/releases/2.0.0.md +22 -0
- package/package.json +1 -1
- package/src/conformance/adapter.ts +55 -70
- package/src/conformance/index.ts +6 -14
- package/src/protocol/contract.ts +1 -1
- package/src/protocol/coordination.ts +2 -48
- package/src/protocol/types.ts +0 -11
- package/src/protocol/version.ts +2 -2
|
@@ -282,7 +282,6 @@ export const ADAPTER_CONFORMANCE_FIXTURES = [
|
|
|
282
282
|
{ id: 'cursor.explicit-expiry', area: 'cursor' },
|
|
283
283
|
{ id: 'acks.idempotent', area: 'acks' },
|
|
284
284
|
{ id: 'acks.status-query', area: 'acks' },
|
|
285
|
-
{ id: 'claims.durable-noncursor', area: 'claims' },
|
|
286
285
|
{ id: 'decisions.topic-supersession', area: 'decisions' },
|
|
287
286
|
{ id: 'security.drone-management-authorization', area: 'security' },
|
|
288
287
|
{ id: 'security.manage-access-matrix', area: 'security' },
|
|
@@ -318,7 +317,6 @@ const FIXTURE_PREREQUISITES: Partial<Record<AdapterConformanceFixtureId, readonl
|
|
|
318
317
|
'cursor.explicit-expiry': ['shared.enrolled-principals'],
|
|
319
318
|
'acks.idempotent': ['shared.enrolled-principals'],
|
|
320
319
|
'acks.status-query': ['shared.enrolled-principals'],
|
|
321
|
-
'claims.durable-noncursor': ['shared.enrolled-principals'],
|
|
322
320
|
'decisions.topic-supersession': ['shared.enrolled-principals'],
|
|
323
321
|
'security.manage-access-matrix': ['shared.enrolled-principals'],
|
|
324
322
|
'drones.reassign-invariants': ['shared.enrolled-principals'],
|
|
@@ -814,6 +812,20 @@ export async function runAdapterConformance(
|
|
|
814
812
|
const createdResponse = await environment.operations.createCube(ownerCredential, createProtocolEnvelope('cube-create', cubeRequest));
|
|
815
813
|
expectStatus(createdResponse, 201, 'Owner cube create');
|
|
816
814
|
const created = decodeCreateCubeResponseEnvelope(createdResponse.body).payload;
|
|
815
|
+
expectError(
|
|
816
|
+
await environment.operations.createCube(ownerCredential, createProtocolEnvelope('cube-case-variant-duplicate', {
|
|
817
|
+
...cubeRequest,
|
|
818
|
+
retry_key: '00000000-0000-4000-8000-000000000214',
|
|
819
|
+
name: 'repository one',
|
|
820
|
+
repository: {
|
|
821
|
+
kind: 'origin' as const,
|
|
822
|
+
value: 'https://github.com/Byte-Ventures/repository-one-case-variant',
|
|
823
|
+
},
|
|
824
|
+
})),
|
|
825
|
+
409,
|
|
826
|
+
ErrorCode.INVALID_INPUT,
|
|
827
|
+
'Same-owner case-variant cube name',
|
|
828
|
+
);
|
|
817
829
|
const createdRoleProbes = new Map<string, {
|
|
818
830
|
role: unknown;
|
|
819
831
|
droneId: string;
|
|
@@ -1158,26 +1170,27 @@ export async function runAdapterConformance(
|
|
|
1158
1170
|
same(await resolve('repository-resolve-alternate-after-repository-conflict', alternateResolveRequest), { result: 'none' }),
|
|
1159
1171
|
'Repository conflict created an alternate binding.',
|
|
1160
1172
|
);
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
}),
|
|
1168
|
-
),
|
|
1169
|
-
409,
|
|
1170
|
-
ErrorCode.CUBE_ALREADY_ASSOCIATED,
|
|
1171
|
-
'Cube-to-other-repository conflict',
|
|
1172
|
-
[cubeA.id, repository.value, 'https://github.com/Byte-Ventures/other-repository'],
|
|
1173
|
+
const alternateAssociationResponse = await environment.operations.associateRepositoryCube(
|
|
1174
|
+
credentialA,
|
|
1175
|
+
createProtocolEnvelope('repository-associate-second-repository', {
|
|
1176
|
+
cube_id: cubeA.id,
|
|
1177
|
+
...alternateResolveRequest,
|
|
1178
|
+
}),
|
|
1173
1179
|
);
|
|
1180
|
+
expectStatus(alternateAssociationResponse, 200, 'Second repository association');
|
|
1181
|
+
const alternateAuthoritative = decodeAssociateRepositoryCubeResponseEnvelope(
|
|
1182
|
+
alternateAssociationResponse.body,
|
|
1183
|
+
).payload;
|
|
1174
1184
|
invariant(
|
|
1175
|
-
same(await resolve('repository-resolve-after-
|
|
1176
|
-
'
|
|
1185
|
+
same(await resolve('repository-resolve-after-second-association', resolveRequest), authoritative),
|
|
1186
|
+
'Second repository association changed the authoritative original binding.',
|
|
1177
1187
|
);
|
|
1178
1188
|
invariant(
|
|
1179
|
-
same(
|
|
1180
|
-
|
|
1189
|
+
same(
|
|
1190
|
+
await resolve('repository-resolve-alternate-after-second-association', alternateResolveRequest),
|
|
1191
|
+
alternateAuthoritative,
|
|
1192
|
+
),
|
|
1193
|
+
'Second repository association was not observable.',
|
|
1181
1194
|
);
|
|
1182
1195
|
const preparedB = await environment.admin.prepareRepositoryCube(cubeB, {
|
|
1183
1196
|
name: 'Other Client Legacy Cube',
|
|
@@ -1254,7 +1267,7 @@ export async function runAdapterConformance(
|
|
|
1254
1267
|
resolved: true,
|
|
1255
1268
|
idempotent: true,
|
|
1256
1269
|
repository_conflict: ErrorCode.REPOSITORY_ALREADY_ASSOCIATED,
|
|
1257
|
-
|
|
1270
|
+
multiple_repositories_per_cube: true,
|
|
1258
1271
|
inaccessible: ErrorCode.ACCESS_DENIED,
|
|
1259
1272
|
inaccessible_binding_hidden: true,
|
|
1260
1273
|
cross_client_binding_hidden: true,
|
|
@@ -2259,42 +2272,6 @@ export async function runAdapterConformance(
|
|
|
2259
2272
|
};
|
|
2260
2273
|
});
|
|
2261
2274
|
|
|
2262
|
-
await record('claims.durable-noncursor', async () => {
|
|
2263
|
-
const principal = await environment.admin.createPrincipal('claim-noncursor');
|
|
2264
|
-
const cube = await environment.admin.createCube('claim-noncursor');
|
|
2265
|
-
await environment.admin.grantCube(principal, cube);
|
|
2266
|
-
const credential = await environment.admin.issueDroneSession(principal);
|
|
2267
|
-
const appended = await environment.operations.append(
|
|
2268
|
-
credential,
|
|
2269
|
-
cube,
|
|
2270
|
-
createProtocolEnvelope('claim-fixture-entry', {
|
|
2271
|
-
post_id: '00000000-0000-4000-8000-000000000314',
|
|
2272
|
-
to: 'broadcast',
|
|
2273
|
-
message: 'claim cursor baseline',
|
|
2274
|
-
}),
|
|
2275
|
-
);
|
|
2276
|
-
expectStatus(appended, 201, 'Claim fixture append');
|
|
2277
|
-
const entry = decodeAppendLogResultEnvelope(appended.body).payload.entry;
|
|
2278
|
-
const baselineCursor = { id: entry.id, created_at: entry.created_at };
|
|
2279
|
-
const claim = await environment.operations.ack(
|
|
2280
|
-
credential,
|
|
2281
|
-
cube,
|
|
2282
|
-
createProtocolEnvelope('claim-fixture-claim', { entry_id: entry.id, kind: 'claim' }),
|
|
2283
|
-
);
|
|
2284
|
-
expectStatus(claim, 204, 'Claim');
|
|
2285
|
-
const read = await environment.operations.read(
|
|
2286
|
-
credential,
|
|
2287
|
-
cube,
|
|
2288
|
-
createProtocolEnvelope('claim-fixture-readback', { cursor: baselineCursor, limit: 10 }),
|
|
2289
|
-
);
|
|
2290
|
-
expectStatus(read, 200, 'Claim-state read');
|
|
2291
|
-
const page = decodeReadLogResultEnvelope(read.body).payload;
|
|
2292
|
-
invariant(page.entries.length === 0, 'Claim unexpectedly created a log entry.');
|
|
2293
|
-
invariant(page.cursor !== null && compareLogCursor(page.cursor, baselineCursor) === 0, 'Claim advanced the log cursor.');
|
|
2294
|
-
invariant(page.claims.some((item) => item.log_entry_id === entry.id), 'Claim was not durable in a later read.');
|
|
2295
|
-
return { durable_claims: 1, entries: 0, cursor_advanced: false };
|
|
2296
|
-
});
|
|
2297
|
-
|
|
2298
2275
|
await record('decisions.topic-supersession', async () => {
|
|
2299
2276
|
const firstResponse = await environment.operations.recordDecision(
|
|
2300
2277
|
credentialA,
|
|
@@ -3233,24 +3210,25 @@ export async function runAdapterConformance(
|
|
|
3233
3210
|
name: 'Ambiguous Role',
|
|
3234
3211
|
detailedDescription,
|
|
3235
3212
|
});
|
|
3236
|
-
await environment.admin.createRole(roleContractCube, {
|
|
3237
|
-
roleClass: 'worker',
|
|
3238
|
-
isHumanSeat: false,
|
|
3239
|
-
name: 'AMBIGUOUS ROLE',
|
|
3240
|
-
detailedDescription,
|
|
3241
|
-
});
|
|
3242
3213
|
expectError(
|
|
3243
|
-
await environment.operations.
|
|
3244
|
-
|
|
3214
|
+
await environment.operations.createRole(
|
|
3215
|
+
roleContractCredential,
|
|
3245
3216
|
roleContractCube,
|
|
3246
|
-
createProtocolEnvelope('
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3217
|
+
createProtocolEnvelope('role-case-variant-duplicate', { name: 'AMBIGUOUS ROLE' }),
|
|
3218
|
+
),
|
|
3219
|
+
409,
|
|
3220
|
+
ErrorCode.INVALID_INPUT,
|
|
3221
|
+
'Case-variant duplicate role name',
|
|
3222
|
+
);
|
|
3223
|
+
expectError(
|
|
3224
|
+
await environment.operations.createRole(
|
|
3225
|
+
roleContractCredential,
|
|
3226
|
+
roleContractCube,
|
|
3227
|
+
createProtocolEnvelope('role-invalid-character', { name: 'Invalid/Role' }),
|
|
3250
3228
|
),
|
|
3251
3229
|
400,
|
|
3252
3230
|
ErrorCode.INVALID_INPUT,
|
|
3253
|
-
'
|
|
3231
|
+
'Invalid role name character',
|
|
3254
3232
|
);
|
|
3255
3233
|
expectError(
|
|
3256
3234
|
await environment.operations.roleRationale(
|
|
@@ -3273,7 +3251,8 @@ export async function runAdapterConformance(
|
|
|
3273
3251
|
unknown_role_code: ErrorCode.ROLE_NOT_FOUND,
|
|
3274
3252
|
inaccessible_role_code: ErrorCode.ROLE_NOT_FOUND,
|
|
3275
3253
|
unknown_section_code: ErrorCode.ROLE_SECTION_NOT_FOUND,
|
|
3276
|
-
|
|
3254
|
+
case_variant_duplicate_status: 409,
|
|
3255
|
+
invalid_name_code: ErrorCode.INVALID_INPUT,
|
|
3277
3256
|
invalid_selector_code: ErrorCode.INVALID_INPUT,
|
|
3278
3257
|
};
|
|
3279
3258
|
});
|
|
@@ -3861,6 +3840,12 @@ export async function runAdapterConformance(
|
|
|
3861
3840
|
);
|
|
3862
3841
|
expectStatus(log, 200, `${label} deletion log readback`);
|
|
3863
3842
|
const logPayload = decodeReadLogResultEnvelope(log.body).payload;
|
|
3843
|
+
const claimStatus = await environment.operations.ackStatus(
|
|
3844
|
+
manager.credential,
|
|
3845
|
+
cube,
|
|
3846
|
+
createProtocolEnvelope(`delete-${label}-claim-readback`, { entry_id: entry.id }),
|
|
3847
|
+
);
|
|
3848
|
+
expectStatus(claimStatus, 200, `${label} deletion claim readback`);
|
|
3864
3849
|
const roster = await environment.operations.listDrones(manager.credential, cube);
|
|
3865
3850
|
expectStatus(roster, 200, `${label} deletion roster readback`);
|
|
3866
3851
|
const roleReadback = await environment.operations.attach(
|
|
@@ -3877,7 +3862,7 @@ export async function runAdapterConformance(
|
|
|
3877
3862
|
return {
|
|
3878
3863
|
decisions: active,
|
|
3879
3864
|
entries: logPayload.entries,
|
|
3880
|
-
claims:
|
|
3865
|
+
claims: decodeAckStatusResultEnvelope(claimStatus.body).payload.claims,
|
|
3881
3866
|
drone: listedDrone(roster, drone.id),
|
|
3882
3867
|
role: rolePayload,
|
|
3883
3868
|
};
|
package/src/conformance/index.ts
CHANGED
|
@@ -474,7 +474,7 @@ export interface CubeTemplateAcceptanceConformanceVector {
|
|
|
474
474
|
accepts: boolean;
|
|
475
475
|
}
|
|
476
476
|
|
|
477
|
-
/** Protocol
|
|
477
|
+
/** Protocol v14's complete closed acceptance set for cube-creation templates. */
|
|
478
478
|
export const CUBE_TEMPLATE_ACCEPTANCE_CONFORMANCE:
|
|
479
479
|
readonly CubeTemplateAcceptanceConformanceVector[] = [
|
|
480
480
|
{ name: 'accepts the software-development template', template: 'software-dev', accepts: true },
|
|
@@ -656,9 +656,9 @@ export interface AssociateRepositoryCubeConformanceVector {
|
|
|
656
656
|
status: 200;
|
|
657
657
|
}
|
|
658
658
|
| {
|
|
659
|
-
outcome: 'repository_conflict'
|
|
659
|
+
outcome: 'repository_conflict';
|
|
660
660
|
status: 409;
|
|
661
|
-
error: 'REPOSITORY_ALREADY_ASSOCIATED'
|
|
661
|
+
error: 'REPOSITORY_ALREADY_ASSOCIATED';
|
|
662
662
|
diagnostic_disclosure: 'none';
|
|
663
663
|
};
|
|
664
664
|
}
|
|
@@ -687,14 +687,12 @@ readonly AssociateRepositoryCubeConformanceVector[] = [
|
|
|
687
687
|
},
|
|
688
688
|
},
|
|
689
689
|
{
|
|
690
|
-
name: '
|
|
690
|
+
name: 'a second repository may associate with the same explicit cube',
|
|
691
691
|
initial: { cube_id: REPOSITORY_CUBE_ONE, ...REPOSITORY_ONE },
|
|
692
692
|
retry: { cube_id: REPOSITORY_CUBE_ONE, ...REPOSITORY_TWO },
|
|
693
693
|
expected: {
|
|
694
|
-
outcome: '
|
|
695
|
-
status:
|
|
696
|
-
error: 'CUBE_ALREADY_ASSOCIATED',
|
|
697
|
-
diagnostic_disclosure: 'none',
|
|
694
|
+
outcome: 'resolved',
|
|
695
|
+
status: 200,
|
|
698
696
|
},
|
|
699
697
|
},
|
|
700
698
|
];
|
|
@@ -949,7 +947,6 @@ export interface RoleRationaleConformanceVector {
|
|
|
949
947
|
| 'unknown-role'
|
|
950
948
|
| 'inaccessible-role'
|
|
951
949
|
| 'unknown-section'
|
|
952
|
-
| 'ambiguous-role-name'
|
|
953
950
|
| 'invalid-selector';
|
|
954
951
|
expected:
|
|
955
952
|
| { status: 200; canonical_heading: true; exact_body: true; mutation: 'none' }
|
|
@@ -984,11 +981,6 @@ export const ROLE_RATIONALE_CONFORMANCE: readonly RoleRationaleConformanceVector
|
|
|
984
981
|
fixture: 'unknown-section',
|
|
985
982
|
expected: { status: 404, error: 'ROLE_SECTION_NOT_FOUND', mutation: 'none' },
|
|
986
983
|
},
|
|
987
|
-
{
|
|
988
|
-
name: 'rejects a role name with multiple case-insensitive matches',
|
|
989
|
-
fixture: 'ambiguous-role-name',
|
|
990
|
-
expected: { status: 400, error: 'INVALID_INPUT', mutation: 'none' },
|
|
991
|
-
},
|
|
992
984
|
{
|
|
993
985
|
name: 'rejects malformed or ambiguous selectors',
|
|
994
986
|
fixture: 'invalid-selector',
|
package/src/protocol/contract.ts
CHANGED
|
@@ -13,7 +13,7 @@ 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 = '
|
|
16
|
+
export const SHARED_PACKAGE_VERSION = '2.0.0' 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
19
|
/** Maximum UTF-8 size of role detailed-description text and any returned section slice. */
|
|
@@ -26,15 +26,6 @@ export interface ReadLogRequest {
|
|
|
26
26
|
limit?: number;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
export interface ClaimRecord {
|
|
30
|
-
log_entry_id: string;
|
|
31
|
-
claimant_drone_id: string;
|
|
32
|
-
claimant_label: string | null;
|
|
33
|
-
claimant_role: string | null;
|
|
34
|
-
claimed_at: string;
|
|
35
|
-
stale: boolean;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
29
|
export interface AppendLogResult extends Omit<AppendLogResponse, 'entry'> {
|
|
39
30
|
entry: EnrichedStreamEntry;
|
|
40
31
|
}
|
|
@@ -44,7 +35,6 @@ export interface ReadLogResult {
|
|
|
44
35
|
cursor: LogCursor | null;
|
|
45
36
|
behind_by: number;
|
|
46
37
|
has_more: boolean;
|
|
47
|
-
claims: ClaimRecord[];
|
|
48
38
|
}
|
|
49
39
|
|
|
50
40
|
export interface EntryQueryRequest {
|
|
@@ -443,38 +433,6 @@ export function decodeAckStatusResultEnvelope(
|
|
|
443
433
|
return decodeProtocolEnvelope(value, decodeAckStatusResult);
|
|
444
434
|
}
|
|
445
435
|
|
|
446
|
-
function decodeClaimRecord(value: unknown): ClaimRecord {
|
|
447
|
-
const input = object(value);
|
|
448
|
-
exact(
|
|
449
|
-
input,
|
|
450
|
-
[
|
|
451
|
-
'log_entry_id',
|
|
452
|
-
'claimant_drone_id',
|
|
453
|
-
'claimant_label',
|
|
454
|
-
'claimant_role',
|
|
455
|
-
'claimed_at',
|
|
456
|
-
'stale',
|
|
457
|
-
],
|
|
458
|
-
[
|
|
459
|
-
'log_entry_id',
|
|
460
|
-
'claimant_drone_id',
|
|
461
|
-
'claimant_label',
|
|
462
|
-
'claimant_role',
|
|
463
|
-
'claimed_at',
|
|
464
|
-
'stale',
|
|
465
|
-
],
|
|
466
|
-
);
|
|
467
|
-
if (typeof input.stale !== 'boolean') throw new ProtocolContractError('Invalid claim stale flag.');
|
|
468
|
-
return {
|
|
469
|
-
log_entry_id: decodeUuid(input.log_entry_id, ['log_entry_id']),
|
|
470
|
-
claimant_drone_id: decodeUuid(input.claimant_drone_id, ['claimant_drone_id']),
|
|
471
|
-
claimant_label: nullableString(input.claimant_label, 'claimant_label', 120),
|
|
472
|
-
claimant_role: nullableString(input.claimant_role, 'claimant_role', 120),
|
|
473
|
-
claimed_at: decodeCanonicalTimestamp(input.claimed_at, ['claimed_at']),
|
|
474
|
-
stale: input.stale,
|
|
475
|
-
};
|
|
476
|
-
}
|
|
477
|
-
|
|
478
436
|
function decodeRoutingEcho(value: unknown): RoutingEcho {
|
|
479
437
|
const input = object(value);
|
|
480
438
|
exact(
|
|
@@ -549,15 +507,12 @@ export function decodeReadLogResult(value: unknown): ReadLogResult {
|
|
|
549
507
|
const input = object(value);
|
|
550
508
|
exact(
|
|
551
509
|
input,
|
|
552
|
-
['entries', 'cursor', 'behind_by', 'has_more'
|
|
553
|
-
['entries', 'cursor', 'behind_by', 'has_more'
|
|
510
|
+
['entries', 'cursor', 'behind_by', 'has_more'],
|
|
511
|
+
['entries', 'cursor', 'behind_by', 'has_more'],
|
|
554
512
|
);
|
|
555
513
|
if (!Array.isArray(input.entries) || input.entries.length > 500) {
|
|
556
514
|
throw new ProtocolContractError('Invalid read-log entries.');
|
|
557
515
|
}
|
|
558
|
-
if (!Array.isArray(input.claims) || input.claims.length > 500) {
|
|
559
|
-
throw new ProtocolContractError('Invalid read-log claims.');
|
|
560
|
-
}
|
|
561
516
|
if (typeof input.has_more !== 'boolean') throw new ProtocolContractError('Invalid has_more flag.');
|
|
562
517
|
const entries = input.entries.map(decodeEnrichedStreamEntry);
|
|
563
518
|
const cursor = input.cursor === null ? null : decodeLogCursor(input.cursor, ['cursor']);
|
|
@@ -579,7 +534,6 @@ export function decodeReadLogResult(value: unknown): ReadLogResult {
|
|
|
579
534
|
cursor,
|
|
580
535
|
behind_by: nonNegativeInteger(input.behind_by, 'behind_by', Number.MAX_SAFE_INTEGER),
|
|
581
536
|
has_more: input.has_more,
|
|
582
|
-
claims: input.claims.map(decodeClaimRecord),
|
|
583
537
|
};
|
|
584
538
|
}
|
|
585
539
|
|
package/src/protocol/types.ts
CHANGED
|
@@ -146,23 +146,12 @@ export interface RosterResponse {
|
|
|
146
146
|
since?: string | null;
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
export interface ReadLogClaim {
|
|
150
|
-
log_entry_id: string;
|
|
151
|
-
claimant_drone_id: string;
|
|
152
|
-
claimant_label: string | null;
|
|
153
|
-
claimant_role: string | null;
|
|
154
|
-
claimed_at: string;
|
|
155
|
-
stale: boolean;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
149
|
export interface ReadLogResponse {
|
|
159
150
|
entries: ActivityLogEntry[];
|
|
160
151
|
drones: Drone[];
|
|
161
152
|
roles: PublicRole[];
|
|
162
153
|
behind_by?: number;
|
|
163
154
|
has_more?: boolean;
|
|
164
|
-
/** Added with advisory claims; optional when reading older servers. */
|
|
165
|
-
claims?: ReadLogClaim[];
|
|
166
155
|
}
|
|
167
156
|
|
|
168
157
|
export interface RoutingEcho {
|
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 v14. */
|
|
2
|
+
export const PROTOCOL_VERSION = '14' as const;
|
|
3
3
|
|
|
4
4
|
export type ProtocolVersion = typeof PROTOCOL_VERSION;
|