borgmcp-shared 0.6.2 → 0.6.4

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 CHANGED
@@ -59,7 +59,7 @@ functions and contracts include API documentation in their TypeScript sources.
59
59
 
60
60
  ## Handshake
61
61
 
62
- The first-slice HTTP contract has four shared paths:
62
+ The repository-first HTTP contract has six shared paths:
63
63
 
64
64
  - `GET /healthz` is the only unauthenticated liveness probe. Success is `204`
65
65
  with no body or identifying metadata.
@@ -78,6 +78,15 @@ The first-slice HTTP contract has four shared paths:
78
78
  strict, idempotent request selects a server-owned template; one atomic success
79
79
  creates a cube, two initial roles, and the creator's cube-scoped `manage`
80
80
  grant. Exact retries return the same non-secret identities without mutation.
81
+ - `POST /api/repository-cubes/resolve` is an authenticated, read-only lookup by
82
+ canonical repository identity. It returns explicit none or the stored
83
+ authoritative cube, template, role IDs, and repository display without
84
+ inferring identity from a cube name.
85
+ - `PUT /api/repository-cubes/association` atomically binds an explicitly
86
+ confirmed cube ID and canonical repository identity for a caller with cube
87
+ `manage` authority. The same binding is idempotent; repository and cube
88
+ conflicts return distinct non-enumerating error codes, and a conflict,
89
+ validation failure, or permission failure performs no mutation.
81
90
 
82
91
  `decodeProtocolTagPreflight` fails closed on any tag other than the exact
83
92
  expected version, on any extra field, or on a non-object body — before any
@@ -114,7 +123,8 @@ readonly data rather than Vitest-specific helpers, so they work with any test
114
123
  runner and in any JavaScript runtime. Cases cover HTTP and canonical errors,
115
124
  credential misuse, isolation and revocation, SSE framing/replay/cursor ordering,
116
125
  executable enrollment authority/retry/mismatch/redaction and cube-create
117
- idempotency, acks, claims, decisions, cube-scoped drone reassignment, role-class
126
+ idempotency, explicit repository resolution/adoption and conflict atomicity,
127
+ acks, claims, decisions, cube-scoped drone reassignment, role-class
118
128
  and single-seat invariants, eviction exclusion, and terminal bearer signaling.
119
129
  The same runner covers complete attach reports, own-seat metadata self-healing,
120
130
  canonical repository identity, invalid-patch atomicity, cross-cube isolation,
@@ -165,15 +175,19 @@ never published: annotated tag object `90a1cf686a0ce32a7aef836b0b82a930191b9030`
165
175
  peels to protected-main commit `fd69b08586481a60c88099dede8e4e066f73f2f2`;
166
176
  attempt-1 workflow run `30054936226` failed in tests before build, packaging,
167
177
  authentication, or registry mutation and must never be rerun or moved.
168
- `borgmcp-shared@0.6.1` is published and immutable. This source now identifies the
169
- unpublished `0.6.2` Coordinator activation-cadence release. This
178
+ `borgmcp-shared@0.6.1`, `borgmcp-shared@0.6.2`, and
179
+ `borgmcp-shared@0.6.3` are published and immutable. This source now identifies the
180
+ reviewed, unpublished `0.6.4` repository-association hotfix candidate. This
170
181
  reviewed version bump grants no tag or publish authority; creating annotated
171
- `v0.6.2` and publishing
182
+ `v0.6.4` and publishing
172
183
  its exact reviewed artifact remain separate, independently gated steps.
173
- Consumers update shared, server, and client together: peers carrying protocol v2
174
- and v3 reject each other during credential-free preflight. No registry token
175
- belongs in this repository, package metadata, lockfiles, or a committed `.npmrc`;
176
- publishing uses protected external credentials and provenance.
184
+ Consumers update shared, server, and client together: peers carrying protocol v2,
185
+ v3, v4, and v5 reject incompatible tags during credential-free preflight. No
186
+ registry token belongs in this repository, package metadata, lockfiles, or a
187
+ committed `.npmrc`;
188
+ publishing uses protected external credentials and provenance. Successful
189
+ `npm publish` is the workflow terminal boundary; post-publication registry reads
190
+ are outside the immutable release gate.
177
191
 
178
192
  The first client and server releases must consume the reviewed registry release,
179
193
  not a Git, tag, or local-path dependency. Public release requires the
@@ -1,4 +1,4 @@
1
- import { type CreateCubeResponse, type LogCursor, type DroneRuntimeMetadata } from '../protocol/index.js';
1
+ import { type CreateCubeResponse, type CreateCubeRepository, type CubeTemplate, type LogCursor, type DroneRuntimeMetadata } from '../protocol/index.js';
2
2
  export interface ConformanceHttpResponse {
3
3
  status: number;
4
4
  body: unknown;
@@ -65,15 +65,31 @@ export interface ConformanceAuthorityState {
65
65
  grants: number;
66
66
  server_capabilities: number;
67
67
  cube_create_bindings: number;
68
+ repository_associations: number;
68
69
  }
69
70
  export interface ConformanceCreatedCubeState {
70
71
  cube_exists: boolean;
71
72
  creator_has_grant: boolean;
73
+ creator_access: 'manage' | null;
72
74
  grant_count: number;
73
75
  role_count: number;
76
+ name: string;
77
+ working_repo_name: string;
78
+ repository: CreateCubeRepository;
79
+ template: CubeTemplate;
80
+ human_seat_role_id: string;
81
+ default_worker_role_id: string;
74
82
  human_seat_role_matches: boolean;
75
83
  default_worker_role_matches: boolean;
76
84
  }
85
+ export interface ConformanceRepositoryCubeFixture {
86
+ cube_id: string;
87
+ name: string;
88
+ template: CubeTemplate;
89
+ human_seat_role_id: string;
90
+ default_worker_role_id: string;
91
+ access: 'manage';
92
+ }
77
93
  export interface ConformanceEnrollmentPrincipalState {
78
94
  response_client_matches: boolean;
79
95
  active_credential_bindings: number;
@@ -91,6 +107,7 @@ export interface ConformanceAdmin {
91
107
  createPrincipal(name: string): Promise<ConformancePrincipal>;
92
108
  createCube(name: string): Promise<ConformanceCube>;
93
109
  grantCube(principal: ConformancePrincipal, cube: ConformanceCube, access?: ConformanceCubeAccess): Promise<void>;
110
+ revokeCubeGrant(principal: ConformancePrincipal, cube: ConformanceCube): Promise<void>;
94
111
  createRole(cube: ConformanceCube, input: {
95
112
  readonly roleClass: 'queen' | 'worker';
96
113
  readonly isHumanSeat: boolean;
@@ -111,6 +128,10 @@ export interface ConformanceAdmin {
111
128
  issueSingleUseInvitation(principal: ConformancePrincipal, purpose: 'owner' | 'client'): Promise<string>;
112
129
  observeAuthorityState(): Promise<ConformanceAuthorityState>;
113
130
  inspectCreatedCube(creator: ConformancePrincipal, response: CreateCubeResponse): Promise<ConformanceCreatedCubeState>;
131
+ prepareRepositoryCube(cube: ConformanceCube, input: {
132
+ name: string;
133
+ template: CubeTemplate;
134
+ }): Promise<ConformanceRepositoryCubeFixture>;
114
135
  inspectEnrollmentPrincipal(principal: ConformancePrincipal, responseClientId: string): Promise<ConformanceEnrollmentPrincipalState>;
115
136
  revokePrincipal(principal: ConformancePrincipal): Promise<void>;
116
137
  expireCursor(cube: ConformanceCube, cursor: LogCursor): Promise<void>;
@@ -121,6 +142,8 @@ export interface ConformanceOperations {
121
142
  protocol(credential: string | null): Promise<ConformanceHttpResponse>;
122
143
  enroll(request: unknown): Promise<ConformanceHttpResponse>;
123
144
  createCube(credential: string | null, request: unknown): Promise<ConformanceHttpResponse>;
145
+ resolveRepositoryCube(credential: string | null, request: unknown): Promise<ConformanceHttpResponse>;
146
+ associateRepositoryCube(credential: string | null, request: unknown): Promise<ConformanceHttpResponse>;
124
147
  attach(credential: string, request: unknown): Promise<ConformanceHttpResponse>;
125
148
  selfMetadataUpdate(credential: string, cube: ConformanceCube, request: unknown): Promise<ConformanceHttpResponse>;
126
149
  append(credential: string, cube: ConformanceCube, request: unknown): Promise<ConformanceHttpResponse>;
@@ -150,6 +173,9 @@ export declare const ADAPTER_CONFORMANCE_FIXTURES: readonly [{
150
173
  }, {
151
174
  readonly id: "enrollment.retry-authority";
152
175
  readonly area: "enrollment";
176
+ }, {
177
+ readonly id: "repository.explicit-association";
178
+ readonly area: "repository";
153
179
  }, {
154
180
  readonly id: "security.adapter-boundary-injection";
155
181
  readonly area: "security";
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/conformance/adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/conformance/adapter.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,10 @@
1
- import { ErrorCode, compareLogCursor, createProtocolEnvelope, decodeCreateCubeResponseEnvelope, decodeAppendLogResultEnvelope, decodeDecisionResultEnvelope, decodeDecisionsResultEnvelope, decodeEnrollmentExchangeResponseEnvelope, decodeAttachResponseEnvelope, decodeDroneRuntimeMetadataPatch, decodeEvictDroneResultEnvelope, decodeProtocolEnvelope, decodeProtocolErrorEnvelope, decodeProtocolTagPreflight, decodeReadLogResultEnvelope, decodeReassignDroneResultEnvelope, decodeUpdateDroneRuntimeMetadataResponseEnvelope, decodeSseFrames, PROTOCOL_LIMIT_CEILINGS, PROTOCOL_HTTP_CONTRACT, PROTOCOL_VERSION, utf8ByteLength, } from '../protocol/index.js';
2
- import { ENROLLMENT_RETRY_CONFORMANCE } from './index.js';
1
+ import { ErrorCode, compareLogCursor, createProtocolEnvelope, decodeAssociateRepositoryCubeResponseEnvelope, decodeCreateCubeResponseEnvelope, decodeAppendLogResultEnvelope, decodeDecisionResultEnvelope, decodeDecisionsResultEnvelope, decodeEnrollmentExchangeResponseEnvelope, decodeAttachResponseEnvelope, decodeDroneRuntimeMetadataPatch, decodeEvictDroneResultEnvelope, decodeProtocolEnvelope, decodeProtocolErrorEnvelope, decodeProtocolTagPreflight, decodeReadLogResultEnvelope, decodeResolveRepositoryCubeResponseEnvelope, decodeReassignDroneResultEnvelope, decodeUpdateDroneRuntimeMetadataResponseEnvelope, decodeSseFrames, PROTOCOL_LIMIT_CEILINGS, PROTOCOL_HTTP_CONTRACT, PROTOCOL_VERSION, utf8ByteLength, } from '../protocol/index.js';
2
+ import { CREATE_CUBE_ASSOCIATION_CONFORMANCE, CREATE_CUBE_RETRY_CONFORMANCE, ENROLLMENT_RETRY_CONFORMANCE, } from './index.js';
3
3
  export const ADAPTER_CONFORMANCE_FIXTURES = [
4
4
  { id: 'http.unauthenticated-liveness', area: 'http' },
5
5
  { id: 'protocol.credential-free-preflight', area: 'protocol' },
6
6
  { id: 'enrollment.retry-authority', area: 'enrollment' },
7
+ { id: 'repository.explicit-association', area: 'repository' },
7
8
  { id: 'security.adapter-boundary-injection', area: 'security' },
8
9
  { id: 'security.oversize-request', area: 'security' },
9
10
  { id: 'security.cross-cube-isolation', area: 'security' },
@@ -285,7 +286,12 @@ export async function runAdapterConformance(environment, options = {}) {
285
286
  assertStateDelta(beforeAuthorityEnrollment, await environment.admin.observeAuthorityState(), { enrolled_clients: 2, enrollment_claims: 2, server_capabilities: 1 }, 'Owner and ordinary enrollment');
286
287
  const cubeRequest = {
287
288
  retry_key: '00000000-0000-4000-8000-000000000213',
288
- name: 'repository-one',
289
+ name: 'Repository One',
290
+ working_repo_name: 'repository-one',
291
+ repository: {
292
+ kind: 'origin',
293
+ value: 'https://github.com/Byte-Ventures/repository-one',
294
+ },
289
295
  template: 'default',
290
296
  };
291
297
  const droneCredential = await environment.admin.issueDroneSession(ownerPrincipal);
@@ -299,47 +305,91 @@ export async function runAdapterConformance(environment, options = {}) {
299
305
  const createdResponse = await environment.operations.createCube(ownerCredential, createProtocolEnvelope('cube-create', cubeRequest));
300
306
  expectStatus(createdResponse, 201, 'Owner cube create');
301
307
  const created = decodeCreateCubeResponseEnvelope(createdResponse.body).payload;
302
- assertStateDelta(beforeCreate, await environment.admin.observeAuthorityState(), { cubes: 1, roles: 2, grants: 1, cube_create_bindings: 1 }, 'Owner cube create');
308
+ assertStateDelta(beforeCreate, await environment.admin.observeAuthorityState(), { cubes: 1, roles: 2, grants: 1, cube_create_bindings: 1, repository_associations: 1 }, 'Owner cube create');
303
309
  invariant(same(await environment.admin.inspectCreatedCube(ownerPrincipal, created), {
304
310
  cube_exists: true,
305
311
  creator_has_grant: true,
312
+ creator_access: 'manage',
306
313
  grant_count: 1,
307
314
  role_count: 2,
315
+ name: cubeRequest.name,
316
+ working_repo_name: cubeRequest.working_repo_name,
317
+ repository: cubeRequest.repository,
318
+ template: cubeRequest.template,
319
+ human_seat_role_id: created.human_seat_role_id,
320
+ default_worker_role_id: created.default_worker_role_id,
308
321
  human_seat_role_matches: true,
309
322
  default_worker_role_matches: true,
310
323
  }), 'Created cube identities or creator grant did not match persisted authority state.');
311
324
  const beforeCreateRetry = await environment.admin.observeAuthorityState();
312
325
  const retriedCreateResponse = await environment.operations.createCube(ownerCredential, createProtocolEnvelope('cube-retry', cubeRequest));
313
326
  expectStatus(retriedCreateResponse, 201, 'Exact cube-create retry');
314
- invariant(same(decodeCreateCubeResponseEnvelope(retriedCreateResponse.body).payload, created), 'Exact cube-create retry returned different identities.');
327
+ const retriedCreate = decodeCreateCubeResponseEnvelope(retriedCreateResponse.body).payload;
328
+ invariant(retriedCreate.result === 'resolved', 'Exact cube-create retry did not report resolved readback.');
329
+ invariant(same({ ...retriedCreate, result: 'created' }, created), 'Exact cube-create retry returned different authoritative fields.');
315
330
  assertStateDelta(beforeCreateRetry, await environment.admin.observeAuthorityState(), {}, 'Exact cube-create retry');
316
- const beforeCreateMismatch = await environment.admin.observeAuthorityState();
317
- expectSecretFreeError(await environment.operations.createCube(ownerCredential, createProtocolEnvelope('cube-mismatch', { ...cubeRequest, name: 'repository-two' })), 409, ErrorCode.INVALID_INPUT, 'Cube-create retry mismatch', [cubeRequest.retry_key]);
318
- assertStateDelta(beforeCreateMismatch, await environment.admin.observeAuthorityState(), {}, 'Cube-create retry mismatch');
331
+ const displayRetryVector = CREATE_CUBE_RETRY_CONFORMANCE.find((vector) => vector.expected.outcome === 'resolved_response' &&
332
+ vector.retry.working_repo_name !== vector.initial.working_repo_name);
333
+ invariant(displayRetryVector !== undefined, 'Missing repository display readback vector.');
334
+ const beforeDisplayRetry = await environment.admin.observeAuthorityState();
335
+ const displayRetryResponse = await environment.operations.createCube(ownerCredential, createProtocolEnvelope('cube-display-retry', {
336
+ ...displayRetryVector.retry,
337
+ retry_key: cubeRequest.retry_key,
338
+ }));
339
+ expectStatus(displayRetryResponse, 201, 'Changed repository display retry');
340
+ invariant(same(decodeCreateCubeResponseEnvelope(displayRetryResponse.body).payload, retriedCreate), 'Changed repository display retry did not return stored authoritative display.');
341
+ assertStateDelta(beforeDisplayRetry, await environment.admin.observeAuthorityState(), {}, 'Changed repository display retry');
342
+ for (const [index, vector] of CREATE_CUBE_RETRY_CONFORMANCE.entries()) {
343
+ if (vector.expected.outcome !== 'retry_tuple_mismatch')
344
+ continue;
345
+ const mismatch = { ...vector.retry, retry_key: cubeRequest.retry_key };
346
+ const beforeCreateMismatch = await environment.admin.observeAuthorityState();
347
+ expectSecretFreeError(await environment.operations.createCube(ownerCredential, createProtocolEnvelope(`cube-mismatch-${index}`, mismatch)), 409, ErrorCode.INVALID_INPUT, `Cube-create ${vector.name}`, [cubeRequest.retry_key]);
348
+ assertStateDelta(beforeCreateMismatch, await environment.admin.observeAuthorityState(), {}, `Cube-create ${vector.name}`);
349
+ }
350
+ const sameAssociationVector = CREATE_CUBE_ASSOCIATION_CONFORMANCE.find((vector) => vector.expected.outcome === 'resolved');
351
+ invariant(sameAssociationVector !== undefined, 'Missing same-repository association vector.');
352
+ const beforeAssociationResolve = await environment.admin.observeAuthorityState();
353
+ const associationResolveResponse = await environment.operations.createCube(ownerCredential, createProtocolEnvelope('cube-association-resolve', {
354
+ ...sameAssociationVector.request,
355
+ repository: cubeRequest.repository,
356
+ }));
357
+ expectStatus(associationResolveResponse, 201, 'Fresh retry for associated repository');
358
+ const associationResolved = decodeCreateCubeResponseEnvelope(associationResolveResponse.body).payload;
359
+ invariant(associationResolved.result === 'resolved', 'Associated repository did not resolve.');
360
+ invariant(same({ ...associationResolved, result: 'created' }, created), 'Associated repository did not return stored authoritative fields.');
361
+ assertStateDelta(beforeAssociationResolve, await environment.admin.observeAuthorityState(), sameAssociationVector.expected.authority_state_delta, 'Fresh retry for associated repository');
319
362
  await environment.admin.grantCreateCubeCapability(ordinaryPrincipal);
320
- const crossClientRequest = { ...cubeRequest, name: 'ordinary-repository' };
363
+ const crossClientRequest = {
364
+ ...cubeRequest,
365
+ working_repo_name: 'ordinary-repository',
366
+ repository: {
367
+ kind: 'local',
368
+ value: '00000000-0000-4000-8000-000000000216',
369
+ },
370
+ };
321
371
  const beforeCrossClientCreate = await environment.admin.observeAuthorityState();
322
372
  const crossClientResponse = await environment.operations.createCube(ordinaryCredential, createProtocolEnvelope('cube-cross-client', crossClientRequest));
323
373
  expectStatus(crossClientResponse, 201, 'Cross-client cube create with reused retry key');
324
374
  const crossClientCreated = decodeCreateCubeResponseEnvelope(crossClientResponse.body).payload;
325
375
  invariant(crossClientCreated.cube_id !== created.cube_id, 'Cross-client retry key reused another client\'s cube.');
326
- assertStateDelta(beforeCrossClientCreate, await environment.admin.observeAuthorityState(), { cubes: 1, roles: 2, grants: 1, cube_create_bindings: 1 }, 'Cross-client cube create');
376
+ assertStateDelta(beforeCrossClientCreate, await environment.admin.observeAuthorityState(), { cubes: 1, roles: 2, grants: 1, cube_create_bindings: 1, repository_associations: 1 }, 'Cross-client cube create');
327
377
  invariant((await environment.admin.inspectCreatedCube(ordinaryPrincipal, crossClientCreated)).creator_has_grant, 'Cross-client cube creation did not grant its authenticated creator.');
328
378
  const beforeCrossClientRetry = await environment.admin.observeAuthorityState();
329
379
  const crossClientRetry = await environment.operations.createCube(ordinaryCredential, createProtocolEnvelope('cube-cross-client-retry', crossClientRequest));
330
380
  expectStatus(crossClientRetry, 201, 'Exact cross-client cube-create retry');
331
- invariant(same(decodeCreateCubeResponseEnvelope(crossClientRetry.body).payload, crossClientCreated), 'Exact cross-client cube-create retry returned different identities.');
381
+ const crossClientResolved = decodeCreateCubeResponseEnvelope(crossClientRetry.body).payload;
382
+ invariant(crossClientResolved.result === 'resolved', 'Exact cross-client cube-create retry did not report resolved readback.');
383
+ invariant(same({ ...crossClientResolved, result: 'created' }, crossClientCreated), 'Exact cross-client cube-create retry returned different authoritative fields.');
332
384
  assertStateDelta(beforeCrossClientRetry, await environment.admin.observeAuthorityState(), {}, 'Exact cross-client cube-create retry');
385
+ const differentAssociationVector = CREATE_CUBE_ASSOCIATION_CONFORMANCE.find((vector) => vector.expected.outcome === 'created');
386
+ invariant(differentAssociationVector !== undefined, 'Missing different-repository association vector.');
333
387
  const beforeSecondCreate = await environment.admin.observeAuthorityState();
334
- const secondCreatedResponse = await environment.operations.createCube(ownerCredential, createProtocolEnvelope('cube-create-second', {
335
- ...cubeRequest,
336
- retry_key: '00000000-0000-4000-8000-000000000214',
337
- name: 'repository-two',
338
- }));
388
+ const secondCreatedResponse = await environment.operations.createCube(ownerCredential, createProtocolEnvelope('cube-create-second', differentAssociationVector.request));
339
389
  expectStatus(secondCreatedResponse, 201, 'Second cube create');
340
390
  const secondCreated = decodeCreateCubeResponseEnvelope(secondCreatedResponse.body).payload;
341
391
  invariant(secondCreated.cube_id !== created.cube_id, 'Fresh cube-create retry key reused an existing cube.');
342
- assertStateDelta(beforeSecondCreate, await environment.admin.observeAuthorityState(), { cubes: 1, roles: 2, grants: 1, cube_create_bindings: 1 }, 'Second cube create');
392
+ assertStateDelta(beforeSecondCreate, await environment.admin.observeAuthorityState(), differentAssociationVector.expected.authority_state_delta, 'Second cube create');
343
393
  await environment.admin.revokePrincipal(ownerPrincipal);
344
394
  const beforeRevokedCreate = await environment.admin.observeAuthorityState();
345
395
  expectSecretFreeError(await environment.operations.createCube(ownerCredential, createProtocolEnvelope('cube-revoked', {
@@ -394,6 +444,123 @@ export async function runAdapterConformance(environment, options = {}) {
394
444
  response_secret_free: true,
395
445
  };
396
446
  });
447
+ await record('repository.explicit-association', async () => {
448
+ const repository = {
449
+ kind: 'origin',
450
+ value: 'https://github.com/Byte-Ventures/legacy-repository',
451
+ };
452
+ const prepared = await environment.admin.prepareRepositoryCube(cubeA, {
453
+ name: 'Legacy Repository Cube',
454
+ template: 'software-dev',
455
+ });
456
+ const resolveRequest = {
457
+ working_repo_name: 'legacy-repository',
458
+ repository,
459
+ };
460
+ const beforeNone = await environment.admin.observeAuthorityState();
461
+ const noneResponse = await environment.operations.resolveRepositoryCube(credentialA, createProtocolEnvelope('repository-resolve-none', resolveRequest));
462
+ expectStatus(noneResponse, 200, 'Unassociated repository resolution');
463
+ invariant(same(decodeResolveRepositoryCubeResponseEnvelope(noneResponse.body).payload, { result: 'none' }), 'Unassociated repository did not return explicit none.');
464
+ assertStateDelta(beforeNone, await environment.admin.observeAuthorityState(), {}, 'Repository resolution');
465
+ const associationRequest = { cube_id: cubeA.id, ...resolveRequest };
466
+ const beforeDenied = await environment.admin.observeAuthorityState();
467
+ expectSecretFreeError(await environment.operations.associateRepositoryCube(credentialB, createProtocolEnvelope('repository-associate-denied', associationRequest)), 403, ErrorCode.ACCESS_DENIED, 'Inaccessible repository cube association', [associationRequest.cube_id, repository.value]);
468
+ assertStateDelta(beforeDenied, await environment.admin.observeAuthorityState(), {}, 'Denied repository association');
469
+ const beforeAssociation = await environment.admin.observeAuthorityState();
470
+ const associatedResponse = await environment.operations.associateRepositoryCube(credentialA, createProtocolEnvelope('repository-associate', associationRequest));
471
+ expectStatus(associatedResponse, 200, 'Explicit repository cube association');
472
+ const associated = decodeAssociateRepositoryCubeResponseEnvelope(associatedResponse.body).payload;
473
+ const authoritative = {
474
+ result: 'resolved',
475
+ cube_id: prepared.cube_id,
476
+ name: prepared.name,
477
+ working_repo_name: resolveRequest.working_repo_name,
478
+ repository,
479
+ template: prepared.template,
480
+ human_seat_role_id: prepared.human_seat_role_id,
481
+ default_worker_role_id: prepared.default_worker_role_id,
482
+ access: prepared.access,
483
+ };
484
+ invariant(same(associated, authoritative), 'Repository association did not return authoritative stored fields.');
485
+ assertStateDelta(beforeAssociation, await environment.admin.observeAuthorityState(), { repository_associations: 1 }, 'Explicit repository association');
486
+ const beforeResolve = await environment.admin.observeAuthorityState();
487
+ const resolvedResponse = await environment.operations.resolveRepositoryCube(credentialA, createProtocolEnvelope('repository-resolve', {
488
+ ...resolveRequest,
489
+ working_repo_name: 'ignored-new-display',
490
+ }));
491
+ expectStatus(resolvedResponse, 200, 'Associated repository resolution');
492
+ invariant(same(decodeResolveRepositoryCubeResponseEnvelope(resolvedResponse.body).payload, authoritative), 'Associated repository did not return stored authoritative display.');
493
+ assertStateDelta(beforeResolve, await environment.admin.observeAuthorityState(), {}, 'Associated repository resolution');
494
+ const beforeRetry = await environment.admin.observeAuthorityState();
495
+ const retryResponse = await environment.operations.associateRepositoryCube(credentialA, createProtocolEnvelope('repository-associate-retry', associationRequest));
496
+ expectStatus(retryResponse, 200, 'Exact repository association retry');
497
+ invariant(same(decodeAssociateRepositoryCubeResponseEnvelope(retryResponse.body).payload, authoritative), 'Exact repository association retry changed authoritative fields.');
498
+ assertStateDelta(beforeRetry, await environment.admin.observeAuthorityState(), {}, 'Repository association retry');
499
+ const cubeC = await environment.admin.createCube('cube-c');
500
+ await environment.admin.grantCube(principalA, cubeC);
501
+ await environment.admin.prepareRepositoryCube(cubeC, {
502
+ name: 'Other Legacy Cube',
503
+ template: 'starter',
504
+ });
505
+ const beforeRepositoryConflict = await environment.admin.observeAuthorityState();
506
+ expectSecretFreeError(await environment.operations.associateRepositoryCube(credentialA, createProtocolEnvelope('repository-associate-repository-conflict', {
507
+ ...associationRequest,
508
+ cube_id: cubeC.id,
509
+ })), 409, ErrorCode.REPOSITORY_ALREADY_ASSOCIATED, 'Repository-to-other-cube conflict', [cubeA.id, cubeC.id, repository.value]);
510
+ assertStateDelta(beforeRepositoryConflict, await environment.admin.observeAuthorityState(), {}, 'Repository-to-other-cube conflict');
511
+ const beforeCubeConflict = await environment.admin.observeAuthorityState();
512
+ expectSecretFreeError(await environment.operations.associateRepositoryCube(credentialA, createProtocolEnvelope('repository-associate-cube-conflict', {
513
+ cube_id: cubeA.id,
514
+ working_repo_name: 'other-repository',
515
+ repository: {
516
+ kind: 'origin',
517
+ value: 'https://github.com/Byte-Ventures/other-repository',
518
+ },
519
+ })), 409, ErrorCode.CUBE_ALREADY_ASSOCIATED, 'Cube-to-other-repository conflict', [cubeA.id, repository.value, 'https://github.com/Byte-Ventures/other-repository']);
520
+ assertStateDelta(beforeCubeConflict, await environment.admin.observeAuthorityState(), {}, 'Cube-to-other-repository conflict');
521
+ const preparedB = await environment.admin.prepareRepositoryCube(cubeB, {
522
+ name: 'Other Client Legacy Cube',
523
+ template: 'starter',
524
+ });
525
+ const beforeCrossClientResolve = await environment.admin.observeAuthorityState();
526
+ const crossClientResolve = await environment.operations.resolveRepositoryCube(credentialB, createProtocolEnvelope('repository-resolve-cross-client', resolveRequest));
527
+ expectStatus(crossClientResolve, 200, 'Cross-client repository resolution');
528
+ invariant(same(decodeResolveRepositoryCubeResponseEnvelope(crossClientResolve.body).payload, { result: 'none' }), 'Another client repository binding was exposed by resolution.');
529
+ assertStateDelta(beforeCrossClientResolve, await environment.admin.observeAuthorityState(), {}, 'Cross-client repository resolution');
530
+ const beforeCrossClientAssociation = await environment.admin.observeAuthorityState();
531
+ const crossClientAssociation = await environment.operations.associateRepositoryCube(credentialB, createProtocolEnvelope('repository-associate-cross-client', {
532
+ ...associationRequest,
533
+ cube_id: cubeB.id,
534
+ }));
535
+ expectStatus(crossClientAssociation, 200, 'Cross-client repository association');
536
+ const crossClientAssociated = decodeAssociateRepositoryCubeResponseEnvelope(crossClientAssociation.body).payload;
537
+ invariant(crossClientAssociated.cube_id === preparedB.cube_id &&
538
+ crossClientAssociated.repository.value === repository.value, 'Another client binding changed cross-client association identity.');
539
+ assertStateDelta(beforeCrossClientAssociation, await environment.admin.observeAuthorityState(), { repository_associations: 1 }, 'Cross-client repository association');
540
+ await environment.admin.revokeCubeGrant(principalA, cubeA);
541
+ const beforeHiddenResolve = await environment.admin.observeAuthorityState();
542
+ const hiddenResolve = await environment.operations.resolveRepositoryCube(credentialA, createProtocolEnvelope('repository-resolve-inaccessible-binding', resolveRequest));
543
+ expectStatus(hiddenResolve, 200, 'Inaccessible repository binding resolution');
544
+ invariant(same(decodeResolveRepositoryCubeResponseEnvelope(hiddenResolve.body).payload, { result: 'none' }), 'Inaccessible repository binding was exposed by read-only resolution.');
545
+ assertStateDelta(beforeHiddenResolve, await environment.admin.observeAuthorityState(), {}, 'Inaccessible repository binding resolution');
546
+ const beforeHiddenAssociation = await environment.admin.observeAuthorityState();
547
+ expectSecretFreeError(await environment.operations.associateRepositoryCube(credentialA, createProtocolEnvelope('repository-associate-inaccessible-binding', {
548
+ ...associationRequest,
549
+ cube_id: cubeC.id,
550
+ })), 403, ErrorCode.ACCESS_DENIED, 'Inaccessible existing repository binding', [cubeA.id, cubeC.id, repository.value]);
551
+ assertStateDelta(beforeHiddenAssociation, await environment.admin.observeAuthorityState(), {}, 'Inaccessible existing repository binding');
552
+ await environment.admin.grantCube(principalA, cubeA);
553
+ return {
554
+ none: true,
555
+ resolved: true,
556
+ idempotent: true,
557
+ repository_conflict: ErrorCode.REPOSITORY_ALREADY_ASSOCIATED,
558
+ cube_conflict: ErrorCode.CUBE_ALREADY_ASSOCIATED,
559
+ inaccessible: ErrorCode.ACCESS_DENIED,
560
+ inaccessible_binding_hidden: true,
561
+ cross_client_binding_hidden: true,
562
+ };
563
+ });
397
564
  await record('security.adapter-boundary-injection', async () => {
398
565
  const injectedMessage = "'); DROP TABLE log_entries; --\r\ndata: forged-sse-frame";
399
566
  const injectedBody = JSON.stringify(createProtocolEnvelope('inject-b1', { message: injectedMessage }));