borgmcp-shared 1.0.1 → 1.2.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.
Files changed (38) hide show
  1. package/CONTRIBUTING.md +4 -1
  2. package/README.md +37 -8
  3. package/RELEASES.md +2 -3
  4. package/dist/conformance/adapter.d.ts +6 -101
  5. package/dist/conformance/adapter.d.ts.map +1 -1
  6. package/dist/conformance/adapter.js +546 -281
  7. package/dist/conformance/adapter.js.map +1 -1
  8. package/dist/conformance/index.d.ts +5 -42
  9. package/dist/conformance/index.d.ts.map +1 -1
  10. package/dist/conformance/index.js +16 -52
  11. package/dist/conformance/index.js.map +1 -1
  12. package/dist/protocol/contract.d.ts +2 -2
  13. package/dist/protocol/contract.d.ts.map +1 -1
  14. package/dist/protocol/contract.js +2 -2
  15. package/dist/protocol/contract.js.map +1 -1
  16. package/dist/protocol/errors.d.ts +0 -14
  17. package/dist/protocol/errors.d.ts.map +1 -1
  18. package/dist/protocol/errors.js +0 -8
  19. package/dist/protocol/errors.js.map +1 -1
  20. package/dist/protocol/version.d.ts +1 -1
  21. package/dist/protocol/version.js +1 -1
  22. package/dist/templates.d.ts +0 -1
  23. package/dist/templates.d.ts.map +1 -1
  24. package/dist/templates.js +1 -2
  25. package/dist/templates.js.map +1 -1
  26. package/docs/compatibility.md +11 -0
  27. package/docs/enrollment.md +6 -9
  28. package/docs/releases/1.1.0.md +19 -0
  29. package/docs/releases/1.2.0.md +20 -0
  30. package/docs/releasing.md +13 -23
  31. package/package.json +1 -2
  32. package/src/conformance/adapter.ts +822 -640
  33. package/src/conformance/index.ts +24 -75
  34. package/src/protocol/contract.ts +2 -2
  35. package/src/protocol/errors.ts +0 -17
  36. package/src/protocol/version.ts +2 -2
  37. package/src/templates.ts +1 -3
  38. package/docs/release-records.json +0 -261
@@ -13,7 +13,6 @@ import {
13
13
  decodeEnrollmentExchangeResponseEnvelope,
14
14
  decodeInvitationArtifact,
15
15
  decodeAttachResponseEnvelope,
16
- decodeDroneRuntimeMetadataPatch,
17
16
  decodeEvictDroneResultEnvelope,
18
17
  decodeDeleteRoleResultEnvelope,
19
18
  decodeRoleRationaleResultEnvelope,
@@ -34,13 +33,10 @@ import {
34
33
  PROTOCOL_VERSION,
35
34
  ROLE_IN_USE_DELETE_MESSAGE,
36
35
  utf8ByteLength,
37
- type CreateCubeResponse,
38
36
  type CreateCubeRepository,
39
37
  type CubeTemplate,
40
- type ResolvedRepositoryCube,
41
38
  type LogCursor,
42
39
  type StreamEvent,
43
- type DroneRuntimeMetadata,
44
40
  type CubeDocument,
45
41
  type EnrichedStreamEntry,
46
42
  } from '../protocol/index.js';
@@ -74,95 +70,8 @@ export interface ConformanceDrone {
74
70
  readonly id: string;
75
71
  }
76
72
 
77
- export interface ConformanceDroneRuntimeState {
78
- readonly metadata: DroneRuntimeMetadata;
79
- readonly metadata_reported: boolean;
80
- readonly metadata_revision: number;
81
- readonly cube_id: string;
82
- readonly role_id: string;
83
- readonly session_state: 'active' | 'revoked';
84
- readonly evicted: boolean;
85
- readonly last_seen: string;
86
- readonly heartbeat_count: number;
87
- readonly wake_count: number;
88
- readonly log_count: number;
89
- readonly model_turn_count: number;
90
- readonly grant_access: ConformanceCubeAccess | null;
91
- readonly server_capabilities: readonly string[];
92
- readonly principal_revoked: boolean;
93
- readonly session_bound: boolean;
94
- readonly last_log_post: string | null;
95
- readonly last_regen_at: string | null;
96
- readonly last_read_log_at: string | null;
97
- readonly last_event_received_at: string | null;
98
- readonly wake_path: 'live';
99
- readonly wake_alert: null;
100
- readonly monitor_armed: boolean;
101
- readonly sse_connected: boolean;
102
- readonly claim_count: number;
103
- readonly decision_count: number;
104
- readonly routing_eligible: boolean;
105
- }
106
-
107
73
  export type ConformanceCubeAccess = 'read' | 'write' | 'manage';
108
74
 
109
- export interface ConformanceCubeManagementState {
110
- readonly directive: string;
111
- readonly taxonomy_marker: string | null;
112
- readonly role_ids: readonly string[];
113
- readonly active_decision_ids: readonly string[];
114
- readonly drones: ReadonlyArray<{
115
- readonly id: string;
116
- readonly role_id: string;
117
- readonly evicted: boolean;
118
- readonly session_revoked: boolean;
119
- }>;
120
- }
121
-
122
- export interface ConformanceAuthorityState {
123
- enrolled_clients: number;
124
- enrollment_claims: number;
125
- activity_acknowledgements: number;
126
- activity_claims: number;
127
- activity_log_entries: number;
128
- cubes: number;
129
- roles: number;
130
- grants: number;
131
- server_capabilities: number;
132
- cube_create_bindings: number;
133
- repository_associations: number;
134
- }
135
-
136
- export interface ConformanceCreatedCubeState {
137
- cube_exists: boolean;
138
- creator_has_grant: boolean;
139
- creator_access: 'manage' | null;
140
- grant_count: number;
141
- role_count: number;
142
- name: string;
143
- working_repo_name: string;
144
- repository: CreateCubeRepository;
145
- template: CubeTemplate;
146
- human_seat_role_id: string;
147
- default_worker_role_id: string;
148
- human_seat_role_matches: boolean;
149
- default_worker_role_matches: boolean;
150
- }
151
-
152
- export interface ConformanceDeletedCubeState {
153
- readonly cube_exists: boolean;
154
- readonly role_count: number;
155
- readonly drone_count: number;
156
- readonly log_count: number;
157
- readonly claim_count: number;
158
- readonly decision_count: number;
159
- readonly grant_count: number;
160
- readonly cube_create_binding_count: number;
161
- readonly repository_association_count: number;
162
- readonly active_stream_count: number;
163
- readonly terminal_credential_count: number;
164
- }
165
-
166
75
  export interface ConformanceRepositoryCubeFixture {
167
76
  cube_id: string;
168
77
  name: string;
@@ -172,18 +81,6 @@ export interface ConformanceRepositoryCubeFixture {
172
81
  access: 'manage';
173
82
  }
174
83
 
175
- export interface ConformanceEnrollmentPrincipalState {
176
- response_client_matches: boolean;
177
- active_credential_bindings: number;
178
- /**
179
- * The principal's currently-bound credential still equals the one it enrolled
180
- * with. Since the credential-free tag preflight cannot probe credentials, this
181
- * out-of-band authority check is what proves a rejected mismatch retry did not
182
- * overwrite the good credential.
183
- */
184
- bound_credential_matches_enrollment: boolean;
185
- }
186
-
187
84
  export interface ConformanceReplayBarrier {
188
85
  /** Resolves after the replay snapshot is read but before live delivery is active. */
189
86
  readonly reached: Promise<void>;
@@ -201,8 +98,6 @@ export interface ConformanceStreamResponse extends ConformanceHttpResponse {
201
98
  */
202
99
  export interface ConformanceAdmin {
203
100
  reset(): Promise<void>;
204
- /** Restarts the authority while preserving durable state. */
205
- restartAuthority(): Promise<void>;
206
101
  createPrincipal(name: string): Promise<ConformancePrincipal>;
207
102
  createCube(name: string): Promise<ConformanceCube>;
208
103
  /** Grants the requested cube authority; omitted access defaults to manage. */
@@ -220,7 +115,15 @@ export interface ConformanceAdmin {
220
115
  readonly isDefault?: boolean;
221
116
  readonly isMandatory?: boolean;
222
117
  }): Promise<ConformanceRole>;
223
- replaceLogEntryId(cube: ConformanceCube, currentId: string, replacementId: string): Promise<void>;
118
+ /**
119
+ * Seeds deterministic IDs required to exercise full, unique-prefix, and
120
+ * ambiguous-prefix lookup. Protocol-assigned random IDs cannot portably
121
+ * guarantee those prefix shapes, so this remains a semantic synthetic control.
122
+ */
123
+ seedEntryQueryIds(
124
+ cube: ConformanceCube,
125
+ entries: readonly { current_id: string; query_id: string }[],
126
+ ): Promise<void>;
224
127
  createDrone(
225
128
  principal: ConformancePrincipal,
226
129
  cube: ConformanceCube,
@@ -228,23 +131,9 @@ export interface ConformanceAdmin {
228
131
  ): Promise<ConformanceDrone>;
229
132
  issueManagedDroneSession(drone: ConformanceDrone): Promise<string>;
230
133
  revokeManagedDroneSession(drone: ConformanceDrone): Promise<void>;
231
- inspectManagedDrone(drone: ConformanceDrone): Promise<{
232
- readonly role_id: string;
233
- readonly evicted: boolean;
234
- readonly session_revoked: boolean;
235
- }>;
236
- inspectDroneRuntimeState(drone: ConformanceDrone): Promise<ConformanceDroneRuntimeState>;
237
- /** Observes every cube field mutated by a represented manage-scoped operation. */
238
- inspectCubeManagementState(cube: ConformanceCube): Promise<ConformanceCubeManagementState>;
239
134
  grantCreateCubeCapability(principal: ConformancePrincipal): Promise<void>;
240
135
  issueDroneSession(principal: ConformancePrincipal): Promise<string>;
241
136
  issueSingleUseInvitation(principal: ConformancePrincipal, purpose: 'owner' | 'client'): Promise<string>;
242
- observeAuthorityState(): Promise<ConformanceAuthorityState>;
243
- inspectCreatedCube(
244
- creator: ConformancePrincipal,
245
- response: CreateCubeResponse,
246
- ): Promise<ConformanceCreatedCubeState>;
247
- inspectDeletedCube(cube: ConformanceCube): Promise<ConformanceDeletedCubeState>;
248
137
  prepareRepositoryCube(
249
138
  cube: ConformanceCube,
250
139
  input: {
@@ -252,10 +141,6 @@ export interface ConformanceAdmin {
252
141
  template: CubeTemplate;
253
142
  },
254
143
  ): Promise<ConformanceRepositoryCubeFixture>;
255
- inspectEnrollmentPrincipal(
256
- principal: ConformancePrincipal,
257
- responseClientId: string,
258
- ): Promise<ConformanceEnrollmentPrincipalState>;
259
144
  revokePrincipal(principal: ConformancePrincipal): Promise<void>;
260
145
  expireCursor(cube: ConformanceCube, cursor: LogCursor): Promise<void>;
261
146
  armReplayTransition(): ConformanceReplayBarrier;
@@ -420,9 +305,39 @@ export const ADAPTER_CONFORMANCE_FIXTURES = [
420
305
  export type AdapterConformanceFixtureId =
421
306
  (typeof ADAPTER_CONFORMANCE_FIXTURES)[number]['id'];
422
307
 
308
+ const FIXTURE_PREREQUISITES: Partial<Record<AdapterConformanceFixtureId, readonly string[]>> = {
309
+ 'repository.explicit-association': ['shared.enrolled-principals'],
310
+ 'documents.lifecycle': ['shared.enrolled-principals'],
311
+ 'security.adapter-boundary-injection': ['shared.enrolled-principals'],
312
+ 'security.oversize-request': ['shared.enrolled-principals'],
313
+ 'security.cross-cube-isolation': ['shared.enrolled-principals'],
314
+ 'log.mandatory-addressing': ['shared.enrolled-principals'],
315
+ 'log.entry-query': ['shared.enrolled-principals'],
316
+ 'log.read-cursor-tuple': ['shared.enrolled-principals'],
317
+ 'sse.replay-live-transition': ['shared.enrolled-principals'],
318
+ 'cursor.explicit-expiry': ['shared.enrolled-principals'],
319
+ 'acks.idempotent': ['shared.enrolled-principals'],
320
+ 'acks.status-query': ['shared.enrolled-principals'],
321
+ 'claims.durable-noncursor': ['shared.enrolled-principals'],
322
+ 'decisions.topic-supersession': ['shared.enrolled-principals'],
323
+ 'security.manage-access-matrix': ['shared.enrolled-principals'],
324
+ 'drones.reassign-invariants': ['shared.enrolled-principals'],
325
+ 'security.cross-cube-drone-management': ['shared.enrolled-principals'],
326
+ 'drones.evict-terminal-signal': ['shared.enrolled-principals'],
327
+ 'metadata.attach-report': ['shared.enrolled-principals'],
328
+ 'metadata.self-heal-patch': ['shared.enrolled-principals', 'shared.metadata-baseline'],
329
+ 'security.metadata-invalid-atomic': ['shared.enrolled-principals', 'shared.metadata-baseline'],
330
+ 'security.metadata-own-seat': ['shared.enrolled-principals', 'shared.metadata-baseline'],
331
+ 'security.metadata-cross-cube-isolation': ['shared.enrolled-principals', 'shared.metadata-baseline'],
332
+ 'security.metadata-noninterference': ['shared.enrolled-principals', 'shared.metadata-baseline'],
333
+ 'security.metadata-secret-non-echo': ['shared.enrolled-principals', 'shared.metadata-baseline'],
334
+ };
335
+
423
336
  export interface AdapterConformanceResult {
424
337
  id: AdapterConformanceFixtureId;
425
338
  ok: boolean;
339
+ /** True when the fixture was not exercised because a named prerequisite failed. */
340
+ skipped?: boolean;
426
341
  observations: Record<string, unknown>;
427
342
  error?: string;
428
343
  }
@@ -604,18 +519,29 @@ function listedDroneIds(response: ConformanceHttpResponse): string[] {
604
519
  }).payload;
605
520
  }
606
521
 
607
- function assertStateDelta(
608
- before: ConformanceAuthorityState,
609
- after: ConformanceAuthorityState,
610
- expected: Partial<ConformanceAuthorityState>,
611
- description: string,
612
- ): void {
613
- for (const key of Object.keys(before) as Array<keyof ConformanceAuthorityState>) {
614
- invariant(
615
- after[key] - before[key] === (expected[key] ?? 0),
616
- `${description} changed ${key} by ${after[key] - before[key]}; expected ${expected[key] ?? 0}.`,
522
+ function listedDrone(response: ConformanceHttpResponse, droneId: string): Record<string, unknown> | null {
523
+ return decodeProtocolEnvelope(response.body, (payload) => {
524
+ invariant(typeof payload === 'object' && payload !== null, 'Roster payload is not an object.');
525
+ const drones = (payload as { drones?: unknown }).drones;
526
+ invariant(Array.isArray(drones), 'Roster payload omitted drones.');
527
+ const drone = drones.find((candidate) =>
528
+ typeof candidate === 'object' && candidate !== null &&
529
+ (candidate as { id?: unknown }).id === droneId
617
530
  );
618
- }
531
+ return drone ? { ...drone as Record<string, unknown> } : null;
532
+ }).payload;
533
+ }
534
+
535
+ function withoutRuntimeMetadata(drone: Record<string, unknown>): Record<string, unknown> {
536
+ const {
537
+ agent_kind: _agentKind,
538
+ reported_model: _reportedModel,
539
+ working_repo_name: _workingRepoName,
540
+ working_repo_origin: _workingRepoOrigin,
541
+ runtime_metadata_reported: _runtimeMetadataReported,
542
+ ...rest
543
+ } = drone;
544
+ return rest;
619
545
  }
620
546
 
621
547
  function assertEnrollmentErrorIsSecretFree(
@@ -657,18 +583,33 @@ export async function runAdapterConformance(
657
583
  invariant(streamDeadlineMs > 0, 'streamDeadlineMs must be positive.');
658
584
  invariant(pendingProbeMs > 0, 'pendingProbeMs must be positive.');
659
585
  const results: AdapterConformanceResult[] = [];
586
+ const prerequisiteFailures = new Map<string, string>();
660
587
  const record = async (
661
588
  id: AdapterConformanceFixtureId,
662
589
  execute: () => Promise<Record<string, unknown>>,
590
+ prerequisites: readonly string[] = [],
663
591
  ): Promise<void> => {
592
+ const required = [...(FIXTURE_PREREQUISITES[id] ?? []), ...prerequisites];
593
+ const failedPrerequisite = required.find((name) => prerequisiteFailures.has(name));
594
+ if (failedPrerequisite) {
595
+ results.push({
596
+ id,
597
+ ok: false,
598
+ skipped: true,
599
+ observations: {},
600
+ error: `Skipped because prerequisite ${failedPrerequisite} failed: ${prerequisiteFailures.get(failedPrerequisite)}`,
601
+ });
602
+ return;
603
+ }
664
604
  try {
665
605
  results.push({ id, ok: true, observations: await execute() });
666
606
  } catch (error) {
607
+ const message = error instanceof Error ? error.message : String(error);
667
608
  results.push({
668
609
  id,
669
610
  ok: false,
670
611
  observations: {},
671
- error: error instanceof Error ? error.message : String(error),
612
+ error: message,
672
613
  });
673
614
  }
674
615
  };
@@ -689,10 +630,8 @@ export async function runAdapterConformance(
689
630
  });
690
631
 
691
632
  await record('protocol.credential-free-preflight', async () => {
692
- // The tag preflight is credential-free (no bearer) and mutation-free: a
693
- // client verifies pinned TLS and the exact tag before it creates or sends any
694
- // credential. The server must answer 200 with ONLY the exact tag.
695
- const before = await environment.admin.observeAuthorityState();
633
+ // The tag preflight is credential-free: a client verifies pinned TLS and the
634
+ // exact tag before it creates or sends any credential.
696
635
  const response = await environment.operations.protocol(null);
697
636
  expectStatus(response, 200, 'Credential-free protocol-tag preflight');
698
637
  const preflight = decodeProtocolTagPreflight(response.body);
@@ -700,8 +639,7 @@ export async function runAdapterConformance(
700
639
  Object.keys(preflight).length === 1 && preflight.protocol_version === PROTOCOL_VERSION,
701
640
  'Protocol-tag preflight exposed more than the exact tag.',
702
641
  );
703
- assertStateDelta(before, await environment.admin.observeAuthorityState(), {}, 'Protocol-tag preflight');
704
- return { authenticated: false, mutation_free: true, protocol_version: preflight.protocol_version };
642
+ return { authenticated: false, protocol_version: preflight.protocol_version };
705
643
  });
706
644
 
707
645
  await record('enrollment.invitation-artifact', async () => {
@@ -738,7 +676,6 @@ export async function runAdapterConformance(
738
676
  const invitation = await environment.admin.issueSingleUseInvitation(principal, purpose);
739
677
  const initialPayload = { ...vector.initial, invitation };
740
678
  const retryPayload = { ...vector.retry, invitation };
741
- const beforeInitial = await environment.admin.observeAuthorityState();
742
679
  const initialResponse = await environment.operations.enroll(
743
680
  createProtocolEnvelope(`retry-${index}-initial`, initialPayload),
744
681
  );
@@ -749,19 +686,6 @@ export async function runAdapterConformance(
749
686
  same(initial.server_capabilities, purpose === 'owner' ? ['create_cube'] : []),
750
687
  `${purpose} ${vector.name} returned incorrect server authority.`,
751
688
  );
752
- const afterInitial = await environment.admin.observeAuthorityState();
753
- assertStateDelta(
754
- beforeInitial,
755
- afterInitial,
756
- {
757
- enrolled_clients: 1,
758
- enrollment_claims: 1,
759
- server_capabilities: purpose === 'owner' ? 1 : 0,
760
- },
761
- `${purpose} ${vector.name} initial request`,
762
- );
763
-
764
- const beforeRetry = await environment.admin.observeAuthorityState();
765
689
  const retryResponse = await environment.operations.enroll(
766
690
  createProtocolEnvelope(`retry-${index}-retry`, retryPayload),
767
691
  );
@@ -780,15 +704,40 @@ export async function runAdapterConformance(
780
704
  `${purpose} ${vector.name}`,
781
705
  );
782
706
  }
783
- assertStateDelta(beforeRetry, await environment.admin.observeAuthorityState(), {}, `${purpose} ${vector.name} retry`);
784
- invariant(
785
- same(await environment.admin.inspectEnrollmentPrincipal(principal, initial.client_id), {
786
- response_client_matches: true,
787
- active_credential_bindings: 1,
788
- bound_credential_matches_enrollment: true,
707
+ const credentialProbeCube = await environment.admin.createCube(`${purpose}-credential-probe-${index}`);
708
+ await environment.admin.grantCube(principal, credentialProbeCube, 'read');
709
+ expectStatus(
710
+ await environment.operations.read(
711
+ initialPayload.client_credential,
712
+ credentialProbeCube,
713
+ createProtocolEnvelope(`retry-${index}-credential-probe`, { cursor: null, limit: 1 }),
714
+ ),
715
+ 200,
716
+ `${purpose} ${vector.name} original credential probe`,
717
+ );
718
+ const capabilityProbe = await environment.operations.createCube(
719
+ initialPayload.client_credential,
720
+ createProtocolEnvelope(`retry-${index}-${purpose}-capability-probe`, {
721
+ retry_key: `10000000-0000-4000-8000-${String(index + (purpose === 'owner' ? 700 : 600)).padStart(12, '0')}`,
722
+ name: `${purpose} capability probe ${index}`,
723
+ working_repo_name: `${purpose}-capability-probe-${index}`,
724
+ repository: {
725
+ kind: 'local',
726
+ value: `20000000-0000-4000-8000-${String(index + (purpose === 'owner' ? 700 : 600)).padStart(12, '0')}`,
727
+ },
728
+ template: 'software-dev',
789
729
  }),
790
- `${purpose} ${vector.name} changed enrollment binding ownership.`,
791
730
  );
731
+ if (purpose === 'owner') {
732
+ expectStatus(capabilityProbe, 201, `${purpose} ${vector.name} capability probe`);
733
+ } else {
734
+ expectError(
735
+ capabilityProbe,
736
+ 403,
737
+ ErrorCode.ACCESS_DENIED,
738
+ `${purpose} ${vector.name} capability probe`,
739
+ );
740
+ }
792
741
  } catch (error) {
793
742
  retryVectorErrors.push(
794
743
  `${purpose} ${vector.name}: ${error instanceof Error ? error.message : String(error)}`,
@@ -805,7 +754,6 @@ export async function runAdapterConformance(
805
754
  const ordinaryInvitation = await environment.admin.issueSingleUseInvitation(ordinaryPrincipal, 'client');
806
755
  const ownerCredential = `${'Q'.repeat(42)}U`;
807
756
  const ordinaryCredential = `${'Y'.repeat(42)}U`;
808
- const beforeAuthorityEnrollment = await environment.admin.observeAuthorityState();
809
757
  const ownerResponse = await environment.operations.enroll(createProtocolEnvelope('owner-enroll', {
810
758
  invitation: ownerInvitation,
811
759
  retry_key: '00000000-0000-4000-8000-000000000211',
@@ -824,13 +772,6 @@ export async function runAdapterConformance(
824
772
  const ordinary = decodeEnrollmentExchangeResponseEnvelope(ordinaryResponse.body).payload;
825
773
  invariant(owner.purpose === 'owner' && same(owner.server_capabilities, ['create_cube']), 'Owner enrollment lacked exact create-cube authority.');
826
774
  invariant(ordinary.purpose === 'client' && ordinary.server_capabilities.length === 0, 'Ordinary enrollment gained authority.');
827
- assertStateDelta(
828
- beforeAuthorityEnrollment,
829
- await environment.admin.observeAuthorityState(),
830
- { enrolled_clients: 2, enrollment_claims: 2, server_capabilities: 1 },
831
- 'Owner and ordinary enrollment',
832
- );
833
-
834
775
  const cubeRequest = {
835
776
  retry_key: '00000000-0000-4000-8000-000000000213',
836
777
  name: 'Repository One',
@@ -839,10 +780,9 @@ export async function runAdapterConformance(
839
780
  kind: 'origin' as const,
840
781
  value: 'https://github.com/Byte-Ventures/repository-one',
841
782
  },
842
- template: 'default',
783
+ template: 'software-dev',
843
784
  };
844
785
  const droneCredential = await environment.admin.issueDroneSession(ownerPrincipal);
845
- const beforeDeniedCreate = await environment.admin.observeAuthorityState();
846
786
  expectSecretFreeError(
847
787
  await environment.operations.createCube(null, createProtocolEnvelope('cube-missing-auth', cubeRequest)),
848
788
  401,
@@ -871,36 +811,56 @@ export async function runAdapterConformance(
871
811
  'Drone-session cube create',
872
812
  [cubeRequest.retry_key],
873
813
  );
874
- assertStateDelta(beforeDeniedCreate, await environment.admin.observeAuthorityState(), {}, 'Denied ordinary cube create');
875
- const beforeCreate = await environment.admin.observeAuthorityState();
876
814
  const createdResponse = await environment.operations.createCube(ownerCredential, createProtocolEnvelope('cube-create', cubeRequest));
877
815
  expectStatus(createdResponse, 201, 'Owner cube create');
878
816
  const created = decodeCreateCubeResponseEnvelope(createdResponse.body).payload;
879
- assertStateDelta(
880
- beforeCreate,
881
- await environment.admin.observeAuthorityState(),
882
- { cubes: 1, roles: 2, grants: 1, cube_create_bindings: 1, repository_associations: 1 },
883
- 'Owner cube create',
884
- );
885
- invariant(
886
- same(await environment.admin.inspectCreatedCube(ownerPrincipal, created), {
887
- cube_exists: true,
888
- creator_has_grant: true,
889
- creator_access: 'manage',
890
- grant_count: 1,
891
- role_count: 2,
892
- name: cubeRequest.name,
893
- working_repo_name: cubeRequest.working_repo_name,
894
- repository: cubeRequest.repository,
895
- template: cubeRequest.template,
896
- human_seat_role_id: created.human_seat_role_id,
897
- default_worker_role_id: created.default_worker_role_id,
898
- human_seat_role_matches: true,
899
- default_worker_role_matches: true,
900
- }),
901
- 'Created cube identities or creator grant did not match persisted authority state.',
902
- );
903
- const beforeCreateRetry = await environment.admin.observeAuthorityState();
817
+ expectError(
818
+ await environment.operations.createCube(ownerCredential, createProtocolEnvelope('cube-case-variant-duplicate', {
819
+ ...cubeRequest,
820
+ retry_key: '00000000-0000-4000-8000-000000000214',
821
+ name: 'repository one',
822
+ repository: {
823
+ kind: 'origin' as const,
824
+ value: 'https://github.com/Byte-Ventures/repository-one-case-variant',
825
+ },
826
+ })),
827
+ 409,
828
+ ErrorCode.INVALID_INPUT,
829
+ 'Same-owner case-variant cube name',
830
+ );
831
+ const createdRoleProbes = new Map<string, {
832
+ role: unknown;
833
+ droneId: string;
834
+ sessionCredential: string;
835
+ }>();
836
+ for (const [kind, roleId, roleClass, isHumanSeat, marker] of [
837
+ ['human-seat', created.human_seat_role_id, 'queen', true, 'H'],
838
+ ['default-worker', created.default_worker_role_id, 'worker', false, 'D'],
839
+ ] as const) {
840
+ const sessionCredential = marker.repeat(43);
841
+ const attached = await environment.operations.attach(
842
+ ownerCredential,
843
+ createProtocolEnvelope(`cube-create-${kind}-probe`, {
844
+ cube_id: created.cube_id,
845
+ role_id: roleId,
846
+ session_credential: sessionCredential,
847
+ }),
848
+ );
849
+ expectStatus(attached, 200, `Created ${kind} role probe`);
850
+ const attachedPayload = decodeAttachResponseEnvelope(attached.body).payload;
851
+ const attachedRole = attachedPayload.role;
852
+ invariant(
853
+ attachedRole.id === roleId &&
854
+ attachedRole.role_class === roleClass &&
855
+ attachedRole.is_human_seat === isHumanSeat,
856
+ `Created ${kind} role identity did not match its protocol role.`,
857
+ );
858
+ createdRoleProbes.set(kind, {
859
+ role: attachedRole,
860
+ droneId: attachedPayload.drone.id,
861
+ sessionCredential,
862
+ });
863
+ }
904
864
  const retriedCreateResponse = await environment.operations.createCube(ownerCredential, createProtocolEnvelope('cube-retry', cubeRequest));
905
865
  expectStatus(retriedCreateResponse, 201, 'Exact cube-create retry');
906
866
  const retriedCreate = decodeCreateCubeResponseEnvelope(retriedCreateResponse.body).payload;
@@ -909,13 +869,11 @@ export async function runAdapterConformance(
909
869
  same({ ...retriedCreate, result: 'created' }, created),
910
870
  'Exact cube-create retry returned different authoritative fields.',
911
871
  );
912
- assertStateDelta(beforeCreateRetry, await environment.admin.observeAuthorityState(), {}, 'Exact cube-create retry');
913
872
  const displayRetryVector = CREATE_CUBE_RETRY_CONFORMANCE.find(
914
873
  (vector) => vector.expected.outcome === 'resolved_response' &&
915
874
  vector.retry.working_repo_name !== vector.initial.working_repo_name,
916
875
  );
917
876
  invariant(displayRetryVector !== undefined, 'Missing repository display readback vector.');
918
- const beforeDisplayRetry = await environment.admin.observeAuthorityState();
919
877
  const displayRetryResponse = await environment.operations.createCube(
920
878
  ownerCredential,
921
879
  createProtocolEnvelope('cube-display-retry', {
@@ -928,16 +886,9 @@ export async function runAdapterConformance(
928
886
  same(decodeCreateCubeResponseEnvelope(displayRetryResponse.body).payload, retriedCreate),
929
887
  'Changed repository display retry did not return stored authoritative display.',
930
888
  );
931
- assertStateDelta(
932
- beforeDisplayRetry,
933
- await environment.admin.observeAuthorityState(),
934
- {},
935
- 'Changed repository display retry',
936
- );
937
889
  for (const [index, vector] of CREATE_CUBE_RETRY_CONFORMANCE.entries()) {
938
890
  if (vector.expected.outcome !== 'retry_tuple_mismatch') continue;
939
891
  const mismatch = { ...vector.retry, retry_key: cubeRequest.retry_key };
940
- const beforeCreateMismatch = await environment.admin.observeAuthorityState();
941
892
  expectSecretFreeError(
942
893
  await environment.operations.createCube(
943
894
  ownerCredential,
@@ -948,18 +899,32 @@ export async function runAdapterConformance(
948
899
  `Cube-create ${vector.name}`,
949
900
  [cubeRequest.retry_key],
950
901
  );
951
- assertStateDelta(
952
- beforeCreateMismatch,
953
- await environment.admin.observeAuthorityState(),
954
- {},
955
- `Cube-create ${vector.name}`,
902
+ }
903
+ for (const [kind, roleId] of [
904
+ ['human-seat', created.human_seat_role_id],
905
+ ['default-worker', created.default_worker_role_id],
906
+ ] as const) {
907
+ const initialProbe = createdRoleProbes.get(kind);
908
+ invariant(initialProbe !== undefined, `Missing initial ${kind} role probe.`);
909
+ const attached = await environment.operations.attach(
910
+ ownerCredential,
911
+ createProtocolEnvelope(`cube-create-${kind}-post-refusal-probe`, {
912
+ cube_id: created.cube_id,
913
+ role_id: roleId,
914
+ session_credential: initialProbe.sessionCredential,
915
+ prior_drone_id: initialProbe.droneId,
916
+ }),
917
+ );
918
+ expectStatus(attached, 200, `Post-refusal ${kind} role probe`);
919
+ invariant(
920
+ same(decodeAttachResponseEnvelope(attached.body).payload.role, initialProbe.role),
921
+ `Cube-create retry refusal changed the full ${kind} role shape.`,
956
922
  );
957
923
  }
958
924
  const sameAssociationVector = CREATE_CUBE_ASSOCIATION_CONFORMANCE.find(
959
925
  (vector) => vector.expected.outcome === 'resolved',
960
926
  );
961
927
  invariant(sameAssociationVector !== undefined, 'Missing same-repository association vector.');
962
- const beforeAssociationResolve = await environment.admin.observeAuthorityState();
963
928
  const associationResolveResponse = await environment.operations.createCube(
964
929
  ownerCredential,
965
930
  createProtocolEnvelope('cube-association-resolve', {
@@ -974,12 +939,6 @@ export async function runAdapterConformance(
974
939
  same({ ...associationResolved, result: 'created' }, created),
975
940
  'Associated repository did not return stored authoritative fields.',
976
941
  );
977
- assertStateDelta(
978
- beforeAssociationResolve,
979
- await environment.admin.observeAuthorityState(),
980
- sameAssociationVector.expected.authority_state_delta,
981
- 'Fresh retry for associated repository',
982
- );
983
942
  await environment.admin.grantCreateCubeCapability(ordinaryPrincipal);
984
943
  const crossClientRequest = {
985
944
  ...cubeRequest,
@@ -989,7 +948,6 @@ export async function runAdapterConformance(
989
948
  value: '00000000-0000-4000-8000-000000000216',
990
949
  },
991
950
  };
992
- const beforeCrossClientCreate = await environment.admin.observeAuthorityState();
993
951
  const crossClientResponse = await environment.operations.createCube(
994
952
  ordinaryCredential,
995
953
  createProtocolEnvelope('cube-cross-client', crossClientRequest),
@@ -997,17 +955,27 @@ export async function runAdapterConformance(
997
955
  expectStatus(crossClientResponse, 201, 'Cross-client cube create with reused retry key');
998
956
  const crossClientCreated = decodeCreateCubeResponseEnvelope(crossClientResponse.body).payload;
999
957
  invariant(crossClientCreated.cube_id !== created.cube_id, 'Cross-client retry key reused another client\'s cube.');
1000
- assertStateDelta(
1001
- beforeCrossClientCreate,
1002
- await environment.admin.observeAuthorityState(),
1003
- { cubes: 1, roles: 2, grants: 1, cube_create_bindings: 1, repository_associations: 1 },
1004
- 'Cross-client cube create',
1005
- );
1006
- invariant(
1007
- (await environment.admin.inspectCreatedCube(ordinaryPrincipal, crossClientCreated)).creator_has_grant,
1008
- 'Cross-client cube creation did not grant its authenticated creator.',
1009
- );
1010
- const beforeCrossClientRetry = await environment.admin.observeAuthorityState();
958
+ for (const [kind, roleId, originalRoleId, marker] of [
959
+ ['human-seat', crossClientCreated.human_seat_role_id, created.human_seat_role_id, 'V'],
960
+ ['default-worker', crossClientCreated.default_worker_role_id, created.default_worker_role_id, 'W'],
961
+ ] as const) {
962
+ const originalProbe = createdRoleProbes.get(kind);
963
+ invariant(originalProbe !== undefined, `Missing original ${kind} role probe.`);
964
+ const attached = await environment.operations.attach(
965
+ ordinaryCredential,
966
+ createProtocolEnvelope(`cube-cross-client-${kind}-probe`, {
967
+ cube_id: crossClientCreated.cube_id,
968
+ role_id: roleId,
969
+ session_credential: marker.repeat(43),
970
+ }),
971
+ );
972
+ expectStatus(attached, 200, `Cross-client ${kind} role probe`);
973
+ const attachedRole = decodeAttachResponseEnvelope(attached.body).payload.role;
974
+ invariant(
975
+ same({ ...attachedRole, id: originalRoleId }, originalProbe.role),
976
+ `Cross-client ${kind} role did not match the full template role shape.`,
977
+ );
978
+ }
1011
979
  const crossClientRetry = await environment.operations.createCube(
1012
980
  ordinaryCredential,
1013
981
  createProtocolEnvelope('cube-cross-client-retry', crossClientRequest),
@@ -1025,12 +993,10 @@ export async function runAdapterConformance(
1025
993
  ),
1026
994
  'Exact cross-client cube-create retry returned different authoritative fields.',
1027
995
  );
1028
- assertStateDelta(beforeCrossClientRetry, await environment.admin.observeAuthorityState(), {}, 'Exact cross-client cube-create retry');
1029
996
  const differentAssociationVector = CREATE_CUBE_ASSOCIATION_CONFORMANCE.find(
1030
997
  (vector) => vector.expected.outcome === 'created',
1031
998
  );
1032
999
  invariant(differentAssociationVector !== undefined, 'Missing different-repository association vector.');
1033
- const beforeSecondCreate = await environment.admin.observeAuthorityState();
1034
1000
  const secondCreatedResponse = await environment.operations.createCube(
1035
1001
  ownerCredential,
1036
1002
  createProtocolEnvelope('cube-create-second', differentAssociationVector.request),
@@ -1038,14 +1004,7 @@ export async function runAdapterConformance(
1038
1004
  expectStatus(secondCreatedResponse, 201, 'Second cube create');
1039
1005
  const secondCreated = decodeCreateCubeResponseEnvelope(secondCreatedResponse.body).payload;
1040
1006
  invariant(secondCreated.cube_id !== created.cube_id, 'Fresh cube-create retry key reused an existing cube.');
1041
- assertStateDelta(
1042
- beforeSecondCreate,
1043
- await environment.admin.observeAuthorityState(),
1044
- differentAssociationVector.expected.authority_state_delta,
1045
- 'Second cube create',
1046
- );
1047
1007
  await environment.admin.revokePrincipal(ownerPrincipal);
1048
- const beforeRevokedCreate = await environment.admin.observeAuthorityState();
1049
1008
  expectSecretFreeError(
1050
1009
  await environment.operations.createCube(ownerCredential, createProtocolEnvelope('cube-revoked', {
1051
1010
  ...cubeRequest,
@@ -1056,8 +1015,16 @@ export async function runAdapterConformance(
1056
1015
  'Revoked owner cube create',
1057
1016
  ['00000000-0000-4000-8000-000000000215'],
1058
1017
  );
1059
- assertStateDelta(beforeRevokedCreate, await environment.admin.observeAuthorityState(), {}, 'Revoked owner cube create');
1060
1018
 
1019
+ return {
1020
+ enrollment_status: 201,
1021
+ exact_retry_status: 201,
1022
+ mismatched_retry: ErrorCode.AUTH_INVALID,
1023
+ response_secret_free: true,
1024
+ };
1025
+ });
1026
+
1027
+ try {
1061
1028
  await environment.admin.reset();
1062
1029
  principalA = await environment.admin.createPrincipal('principal-a');
1063
1030
  principalB = await environment.admin.createPrincipal('principal-b');
@@ -1069,50 +1036,23 @@ export async function runAdapterConformance(
1069
1036
  const invitationB = await environment.admin.issueSingleUseInvitation(principalB, 'client');
1070
1037
  credentialA = 'A'.repeat(43);
1071
1038
  credentialB = 'E'.repeat(43);
1072
- const enrollmentARequest = createProtocolEnvelope('enroll-a1', {
1039
+ const enrolledAResponse = await environment.operations.enroll(createProtocolEnvelope('enroll-a1', {
1073
1040
  invitation: invitationA,
1074
1041
  retry_key: '00000000-0000-4000-8000-000000000201',
1075
1042
  client_credential: credentialA,
1076
1043
  client_name: 'conformance-a',
1077
- });
1078
- const enrollmentBRequest = createProtocolEnvelope('enroll-b1', {
1044
+ }));
1045
+ const enrolledBResponse = await environment.operations.enroll(createProtocolEnvelope('enroll-b1', {
1079
1046
  invitation: invitationB,
1080
1047
  retry_key: '00000000-0000-4000-8000-000000000202',
1081
1048
  client_credential: credentialB,
1082
1049
  client_name: 'conformance-b',
1083
- });
1084
- const enrolledAResponse = await environment.operations.enroll(enrollmentARequest);
1085
- const enrolledBResponse = await environment.operations.enroll(enrollmentBRequest);
1086
- expectStatus(enrolledAResponse, 201, 'Principal A enrollment');
1087
- expectStatus(enrolledBResponse, 201, 'Principal B enrollment');
1088
- const enrolledA = decodeEnrollmentExchangeResponseEnvelope(enrolledAResponse.body).payload;
1089
- const enrolledB = decodeEnrollmentExchangeResponseEnvelope(enrolledBResponse.body).payload;
1090
- invariant(enrolledA.purpose === 'client' && enrolledB.purpose === 'client', 'Ordinary enrollment returned owner authority.');
1091
- invariant(enrolledA.server_capabilities.length === 0 && enrolledB.server_capabilities.length === 0, 'Ordinary enrollment returned a server capability.');
1092
- invariant(!('credential' in enrolledA) && !('credential' in enrolledB), 'Enrollment response returned a bearer.');
1093
- const retriedAResponse = await environment.operations.enroll(enrollmentARequest);
1094
- expectStatus(retriedAResponse, 201, 'Exact enrollment retry');
1095
- invariant(
1096
- JSON.stringify(decodeEnrollmentExchangeResponseEnvelope(retriedAResponse.body).payload) ===
1097
- JSON.stringify(enrolledA),
1098
- 'Exact enrollment retry returned different identities.',
1099
- );
1100
- expectError(
1101
- await environment.operations.enroll(createProtocolEnvelope('enroll-a-mismatch', {
1102
- ...enrollmentARequest.payload,
1103
- retry_key: '00000000-0000-4000-8000-000000000203',
1104
- })),
1105
- 401,
1106
- ErrorCode.AUTH_INVALID,
1107
- 'Enrollment retry mismatch',
1108
- );
1109
- return {
1110
- enrollment_status: 201,
1111
- exact_retry_status: 201,
1112
- mismatched_retry: ErrorCode.AUTH_INVALID,
1113
- response_secret_free: true,
1114
- };
1115
- });
1050
+ }));
1051
+ expectStatus(enrolledAResponse, 201, 'Shared principal A enrollment');
1052
+ expectStatus(enrolledBResponse, 201, 'Shared principal B enrollment');
1053
+ } catch (error) {
1054
+ prerequisiteFailures.set('shared.enrolled-principals', error instanceof Error ? error.message : String(error));
1055
+ }
1116
1056
 
1117
1057
  await record('repository.explicit-association', async () => {
1118
1058
  const repository = {
@@ -1127,7 +1067,21 @@ export async function runAdapterConformance(
1127
1067
  working_repo_name: 'legacy-repository',
1128
1068
  repository,
1129
1069
  };
1130
- const beforeNone = await environment.admin.observeAuthorityState();
1070
+ const alternateResolveRequest = {
1071
+ working_repo_name: 'other-repository',
1072
+ repository: {
1073
+ kind: 'origin' as const,
1074
+ value: 'https://github.com/Byte-Ventures/other-repository',
1075
+ },
1076
+ };
1077
+ const resolve = async (requestId: string, request: typeof resolveRequest) => {
1078
+ const response = await environment.operations.resolveRepositoryCube(
1079
+ credentialA,
1080
+ createProtocolEnvelope(requestId, request),
1081
+ );
1082
+ expectStatus(response, 200, requestId);
1083
+ return decodeResolveRepositoryCubeResponseEnvelope(response.body).payload;
1084
+ };
1131
1085
  const noneResponse = await environment.operations.resolveRepositoryCube(
1132
1086
  credentialA,
1133
1087
  createProtocolEnvelope('repository-resolve-none', resolveRequest),
@@ -1137,10 +1091,11 @@ export async function runAdapterConformance(
1137
1091
  same(decodeResolveRepositoryCubeResponseEnvelope(noneResponse.body).payload, { result: 'none' }),
1138
1092
  'Unassociated repository did not return explicit none.',
1139
1093
  );
1140
- assertStateDelta(beforeNone, await environment.admin.observeAuthorityState(), {}, 'Repository resolution');
1141
-
1094
+ invariant(
1095
+ same(await resolve('repository-resolve-none-readback', resolveRequest), { result: 'none' }),
1096
+ 'Read-only repository resolution created an association.',
1097
+ );
1142
1098
  const associationRequest = { cube_id: cubeA.id, ...resolveRequest };
1143
- const beforeDenied = await environment.admin.observeAuthorityState();
1144
1099
  expectSecretFreeError(
1145
1100
  await environment.operations.associateRepositoryCube(
1146
1101
  credentialB,
@@ -1151,9 +1106,6 @@ export async function runAdapterConformance(
1151
1106
  'Inaccessible repository cube association',
1152
1107
  [associationRequest.cube_id, repository.value],
1153
1108
  );
1154
- assertStateDelta(beforeDenied, await environment.admin.observeAuthorityState(), {}, 'Denied repository association');
1155
-
1156
- const beforeAssociation = await environment.admin.observeAuthorityState();
1157
1109
  const associatedResponse = await environment.operations.associateRepositoryCube(
1158
1110
  credentialA,
1159
1111
  createProtocolEnvelope('repository-associate', associationRequest),
@@ -1172,14 +1124,6 @@ export async function runAdapterConformance(
1172
1124
  access: prepared.access,
1173
1125
  };
1174
1126
  invariant(same(associated, authoritative), 'Repository association did not return authoritative stored fields.');
1175
- assertStateDelta(
1176
- beforeAssociation,
1177
- await environment.admin.observeAuthorityState(),
1178
- { repository_associations: 1 },
1179
- 'Explicit repository association',
1180
- );
1181
-
1182
- const beforeResolve = await environment.admin.observeAuthorityState();
1183
1127
  const resolvedResponse = await environment.operations.resolveRepositoryCube(
1184
1128
  credentialA,
1185
1129
  createProtocolEnvelope('repository-resolve', {
@@ -1192,9 +1136,6 @@ export async function runAdapterConformance(
1192
1136
  same(decodeResolveRepositoryCubeResponseEnvelope(resolvedResponse.body).payload, authoritative),
1193
1137
  'Associated repository did not return stored authoritative display.',
1194
1138
  );
1195
- assertStateDelta(beforeResolve, await environment.admin.observeAuthorityState(), {}, 'Associated repository resolution');
1196
-
1197
- const beforeRetry = await environment.admin.observeAuthorityState();
1198
1139
  const retryResponse = await environment.operations.associateRepositoryCube(
1199
1140
  credentialA,
1200
1141
  createProtocolEnvelope('repository-associate-retry', associationRequest),
@@ -1204,15 +1145,12 @@ export async function runAdapterConformance(
1204
1145
  same(decodeAssociateRepositoryCubeResponseEnvelope(retryResponse.body).payload, authoritative),
1205
1146
  'Exact repository association retry changed authoritative fields.',
1206
1147
  );
1207
- assertStateDelta(beforeRetry, await environment.admin.observeAuthorityState(), {}, 'Repository association retry');
1208
-
1209
1148
  const cubeC = await environment.admin.createCube('cube-c');
1210
1149
  await environment.admin.grantCube(principalA, cubeC);
1211
1150
  await environment.admin.prepareRepositoryCube(cubeC, {
1212
1151
  name: 'Other Legacy Cube',
1213
1152
  template: 'starter',
1214
1153
  });
1215
- const beforeRepositoryConflict = await environment.admin.observeAuthorityState();
1216
1154
  expectSecretFreeError(
1217
1155
  await environment.operations.associateRepositoryCube(
1218
1156
  credentialA,
@@ -1226,43 +1164,40 @@ export async function runAdapterConformance(
1226
1164
  'Repository-to-other-cube conflict',
1227
1165
  [cubeA.id, cubeC.id, repository.value],
1228
1166
  );
1229
- assertStateDelta(
1230
- beforeRepositoryConflict,
1231
- await environment.admin.observeAuthorityState(),
1232
- {},
1233
- 'Repository-to-other-cube conflict',
1167
+ invariant(
1168
+ same(await resolve('repository-resolve-after-repository-conflict', resolveRequest), authoritative),
1169
+ 'Repository conflict changed the authoritative original binding.',
1234
1170
  );
1235
-
1236
- const beforeCubeConflict = await environment.admin.observeAuthorityState();
1237
- expectSecretFreeError(
1238
- await environment.operations.associateRepositoryCube(
1239
- credentialA,
1240
- createProtocolEnvelope('repository-associate-cube-conflict', {
1241
- cube_id: cubeA.id,
1242
- working_repo_name: 'other-repository',
1243
- repository: {
1244
- kind: 'origin',
1245
- value: 'https://github.com/Byte-Ventures/other-repository',
1246
- },
1247
- }),
1248
- ),
1249
- 409,
1250
- ErrorCode.CUBE_ALREADY_ASSOCIATED,
1251
- 'Cube-to-other-repository conflict',
1252
- [cubeA.id, repository.value, 'https://github.com/Byte-Ventures/other-repository'],
1171
+ invariant(
1172
+ same(await resolve('repository-resolve-alternate-after-repository-conflict', alternateResolveRequest), { result: 'none' }),
1173
+ 'Repository conflict created an alternate binding.',
1253
1174
  );
1254
- assertStateDelta(
1255
- beforeCubeConflict,
1256
- await environment.admin.observeAuthorityState(),
1257
- {},
1258
- 'Cube-to-other-repository conflict',
1175
+ const alternateAssociationResponse = await environment.operations.associateRepositoryCube(
1176
+ credentialA,
1177
+ createProtocolEnvelope('repository-associate-second-repository', {
1178
+ cube_id: cubeA.id,
1179
+ ...alternateResolveRequest,
1180
+ }),
1181
+ );
1182
+ expectStatus(alternateAssociationResponse, 200, 'Second repository association');
1183
+ const alternateAuthoritative = decodeAssociateRepositoryCubeResponseEnvelope(
1184
+ alternateAssociationResponse.body,
1185
+ ).payload;
1186
+ invariant(
1187
+ same(await resolve('repository-resolve-after-second-association', resolveRequest), authoritative),
1188
+ 'Second repository association changed the authoritative original binding.',
1189
+ );
1190
+ invariant(
1191
+ same(
1192
+ await resolve('repository-resolve-alternate-after-second-association', alternateResolveRequest),
1193
+ alternateAuthoritative,
1194
+ ),
1195
+ 'Second repository association was not observable.',
1259
1196
  );
1260
-
1261
1197
  const preparedB = await environment.admin.prepareRepositoryCube(cubeB, {
1262
1198
  name: 'Other Client Legacy Cube',
1263
1199
  template: 'starter',
1264
1200
  });
1265
- const beforeCrossClientResolve = await environment.admin.observeAuthorityState();
1266
1201
  const crossClientResolve = await environment.operations.resolveRepositoryCube(
1267
1202
  credentialB,
1268
1203
  createProtocolEnvelope('repository-resolve-cross-client', resolveRequest),
@@ -1272,13 +1207,6 @@ export async function runAdapterConformance(
1272
1207
  same(decodeResolveRepositoryCubeResponseEnvelope(crossClientResolve.body).payload, { result: 'none' }),
1273
1208
  'Another client repository binding was exposed by resolution.',
1274
1209
  );
1275
- assertStateDelta(
1276
- beforeCrossClientResolve,
1277
- await environment.admin.observeAuthorityState(),
1278
- {},
1279
- 'Cross-client repository resolution',
1280
- );
1281
- const beforeCrossClientAssociation = await environment.admin.observeAuthorityState();
1282
1210
  const crossClientAssociation = await environment.operations.associateRepositoryCube(
1283
1211
  credentialB,
1284
1212
  createProtocolEnvelope('repository-associate-cross-client', {
@@ -1295,15 +1223,7 @@ export async function runAdapterConformance(
1295
1223
  crossClientAssociated.repository.value === repository.value,
1296
1224
  'Another client binding changed cross-client association identity.',
1297
1225
  );
1298
- assertStateDelta(
1299
- beforeCrossClientAssociation,
1300
- await environment.admin.observeAuthorityState(),
1301
- { repository_associations: 1 },
1302
- 'Cross-client repository association',
1303
- );
1304
-
1305
1226
  await environment.admin.revokeCubeGrant(principalA, cubeA);
1306
- const beforeHiddenResolve = await environment.admin.observeAuthorityState();
1307
1227
  const hiddenResolve = await environment.operations.resolveRepositoryCube(
1308
1228
  credentialA,
1309
1229
  createProtocolEnvelope('repository-resolve-inaccessible-binding', resolveRequest),
@@ -1313,13 +1233,6 @@ export async function runAdapterConformance(
1313
1233
  same(decodeResolveRepositoryCubeResponseEnvelope(hiddenResolve.body).payload, { result: 'none' }),
1314
1234
  'Inaccessible repository binding was exposed by read-only resolution.',
1315
1235
  );
1316
- assertStateDelta(
1317
- beforeHiddenResolve,
1318
- await environment.admin.observeAuthorityState(),
1319
- {},
1320
- 'Inaccessible repository binding resolution',
1321
- );
1322
- const beforeHiddenAssociation = await environment.admin.observeAuthorityState();
1323
1236
  expectSecretFreeError(
1324
1237
  await environment.operations.associateRepositoryCube(
1325
1238
  credentialA,
@@ -1333,19 +1246,30 @@ export async function runAdapterConformance(
1333
1246
  'Inaccessible existing repository binding',
1334
1247
  [cubeA.id, cubeC.id, repository.value],
1335
1248
  );
1336
- assertStateDelta(
1337
- beforeHiddenAssociation,
1338
- await environment.admin.observeAuthorityState(),
1339
- {},
1340
- 'Inaccessible existing repository binding',
1249
+ const hiddenAfterRefusal = await resolve('repository-resolve-after-inaccessible-refusal', resolveRequest);
1250
+ const alternateAfterRefusal = await resolve(
1251
+ 'repository-resolve-alternate-after-inaccessible-refusal',
1252
+ alternateResolveRequest,
1341
1253
  );
1342
1254
  await environment.admin.grantCube(principalA, cubeA);
1255
+ invariant(
1256
+ same(hiddenAfterRefusal, { result: 'none' }),
1257
+ 'Inaccessible-binding refusal changed the hidden authoritative binding.',
1258
+ );
1259
+ invariant(
1260
+ same(alternateAfterRefusal, { result: 'none' }),
1261
+ 'Inaccessible-binding refusal created an alternate binding.',
1262
+ );
1263
+ invariant(
1264
+ same(await resolve('repository-resolve-restored-after-inaccessible-refusal', resolveRequest), authoritative),
1265
+ 'Inaccessible-binding refusal did not preserve the original binding.',
1266
+ );
1343
1267
  return {
1344
1268
  none: true,
1345
1269
  resolved: true,
1346
1270
  idempotent: true,
1347
1271
  repository_conflict: ErrorCode.REPOSITORY_ALREADY_ASSOCIATED,
1348
- cube_conflict: ErrorCode.CUBE_ALREADY_ASSOCIATED,
1272
+ multiple_repositories_per_cube: true,
1349
1273
  inaccessible: ErrorCode.ACCESS_DENIED,
1350
1274
  inaccessible_binding_hidden: true,
1351
1275
  cross_client_binding_hidden: true,
@@ -1887,7 +1811,6 @@ export async function runAdapterConformance(
1887
1811
  });
1888
1812
  const recipient = await environment.admin.createDrone(principalA, cube, role);
1889
1813
  const message = 'START NOW exact slice';
1890
- const before = await environment.admin.observeAuthorityState();
1891
1814
  expectError(
1892
1815
  await environment.operations.append(
1893
1816
  credentialA,
@@ -1901,8 +1824,6 @@ export async function runAdapterConformance(
1901
1824
  ErrorCode.INVALID_INPUT,
1902
1825
  'Omitted mandatory addressing',
1903
1826
  );
1904
- assertStateDelta(before, await environment.admin.observeAuthorityState(), {}, 'Mandatory-addressing refusal');
1905
-
1906
1827
  const broadcast = await environment.operations.append(
1907
1828
  credentialA,
1908
1829
  cube,
@@ -1940,6 +1861,17 @@ export async function runAdapterConformance(
1940
1861
  directedResult.entry.recipient_drone_ids?.length === 1,
1941
1862
  'Classification changed or fell open the explicit recipient set.',
1942
1863
  );
1864
+ const readback = await environment.operations.read(
1865
+ credentialA,
1866
+ cube,
1867
+ createProtocolEnvelope('mandatory-addressing-readback', { cursor: null, limit: 10 }),
1868
+ );
1869
+ expectStatus(readback, 200, 'Mandatory-addressing persistence readback');
1870
+ const persistedIds = decodeReadLogResultEnvelope(readback.body).payload.entries.map((entry) => entry.id);
1871
+ invariant(
1872
+ same(persistedIds, [broadcastResult.entry.id, directedResult.entry.id]),
1873
+ 'Rejected mandatory-addressing append was persisted.',
1874
+ );
1943
1875
  return { refused_status: 400, code: ErrorCode.INVALID_INPUT, persisted: false, broadcast: true, union: true, no_fall_open: true };
1944
1876
  });
1945
1877
 
@@ -1961,6 +1893,7 @@ export async function runAdapterConformance(
1961
1893
  '22222222-0000-4000-8000-000000000002',
1962
1894
  ];
1963
1895
  const entries: EnrichedStreamEntry[] = [];
1896
+ const idSeeds: Array<{ current_id: string; query_id: string }> = [];
1964
1897
  for (const [index, id] of ids.entries()) {
1965
1898
  const response = await environment.operations.append(
1966
1899
  credentialA,
@@ -1973,9 +1906,10 @@ export async function runAdapterConformance(
1973
1906
  );
1974
1907
  expectStatus(response, 201, `Entry-query fixture append ${index}`);
1975
1908
  const entry = decodeAppendLogResultEnvelope(response.body).payload.entry;
1976
- await environment.admin.replaceLogEntryId(cube, entry.id, id);
1909
+ idSeeds.push({ current_id: entry.id, query_id: id });
1977
1910
  entries.push({ ...entry, id });
1978
1911
  }
1912
+ await environment.admin.seedEntryQueryIds(cube, idSeeds);
1979
1913
 
1980
1914
  expectStatus(
1981
1915
  await environment.operations.ack(
@@ -1996,7 +1930,6 @@ export async function runAdapterConformance(
1996
1930
  'Entry-query claim seed',
1997
1931
  );
1998
1932
 
1999
- const before = await environment.admin.observeAuthorityState();
2000
1933
  for (const [requestId, selector, expectedId] of [
2001
1934
  ['entry-query-full', ids[1], ids[1]],
2002
1935
  ['entry-query-prefix', '11111111', ids[0]],
@@ -2030,7 +1963,6 @@ export async function runAdapterConformance(
2030
1963
  ErrorCode.LOG_ENTRY_PREFIX_AMBIGUOUS,
2031
1964
  'Ambiguous entry query',
2032
1965
  );
2033
- assertStateDelta(before, await environment.admin.observeAuthorityState(), {}, 'Entry query');
2034
1966
  const acknowledgementStatus = decodeAckStatusResultEnvelope((await environment.operations.ackStatus(
2035
1967
  credentialA,
2036
1968
  cube,
@@ -2041,15 +1973,22 @@ export async function runAdapterConformance(
2041
1973
  cube,
2042
1974
  createProtocolEnvelope('entry-query-claim-status', { entry_id: ids[1] }),
2043
1975
  )).body).payload;
1976
+ const acknowledgedRecipients = acknowledgementStatus.recipients.filter(
1977
+ (recipient) => recipient.acknowledged_at !== null,
1978
+ );
2044
1979
  invariant(
2045
- acknowledgementStatus.recipients.some((recipient) =>
2046
- recipient.drone_id === acknowledgedRecipient.id && recipient.acknowledged_at !== null
2047
- ),
2048
- 'Entry query removed the seeded acknowledgement.',
1980
+ acknowledgedRecipients.length === 1 &&
1981
+ acknowledgedRecipients[0].drone_id === acknowledgedRecipient.id &&
1982
+ acknowledgementStatus.recipients.find(
1983
+ (recipient) => recipient.drone_id === claimingRecipient.id,
1984
+ )?.acknowledged_at === null,
1985
+ 'Entry query changed the seeded acknowledgement set.',
2049
1986
  );
2050
1987
  invariant(
2051
- claimStatus.claims.some((claim) => claim.drone_id === claimingRecipient.id),
2052
- 'Entry query removed the seeded claim.',
1988
+ claimStatus.claims.length === 1 &&
1989
+ claimStatus.claims[0].drone_id === claimingRecipient.id &&
1990
+ claimStatus.recipients.every((recipient) => recipient.acknowledged_at === null),
1991
+ 'Entry query changed the seeded claim or acknowledgement set.',
2053
1992
  );
2054
1993
  const unreadResponse = await environment.operations.read(
2055
1994
  credentialA,
@@ -2059,8 +1998,8 @@ export async function runAdapterConformance(
2059
1998
  expectStatus(unreadResponse, 200, 'Entry-query unread read');
2060
1999
  const unread = decodeReadLogResultEnvelope(unreadResponse.body).payload;
2061
2000
  invariant(
2062
- unread.entries.length === entries.length && entries.every((entry) => unread.entries.some((item) => item.id === entry.id)),
2063
- 'Entry query consumed or advanced unread activity.',
2001
+ same(unread.entries, entries),
2002
+ 'Entry query mutated, consumed, or advanced unread activity.',
2064
2003
  );
2065
2004
  return {
2066
2005
  full_uuid: true,
@@ -2074,9 +2013,8 @@ export async function runAdapterConformance(
2074
2013
  };
2075
2014
  });
2076
2015
 
2077
- const entries: Array<{ id: string; created_at: string; message: string }> = [];
2078
- let readCursor: LogCursor | null = null;
2079
2016
  await record('log.read-cursor-tuple', async () => {
2017
+ const entries: Array<{ id: string; created_at: string; message: string }> = [];
2080
2018
  for (const [index, message] of ['alpha', 'beta', 'gamma'].entries()) {
2081
2019
  const response = await environment.operations.append(
2082
2020
  credentialA,
@@ -2105,22 +2043,39 @@ export async function runAdapterConformance(
2105
2043
  page.cursor.id === entries[1].id && page.cursor.created_at === entries[1].created_at,
2106
2044
  'Read cursor does not equal the final delivered entry tuple.',
2107
2045
  );
2108
- readCursor = page.cursor;
2109
2046
  return { messages: ['alpha', 'beta'], has_more: true, behind_by: 1, cursor_matches_last_entry: true };
2110
2047
  });
2111
-
2112
- let liveCursor: LogCursor | null = null;
2113
2048
  await record('sse.replay-live-transition', async () => {
2114
- invariant(readCursor, 'Cursor fixture did not produce a cursor.');
2049
+ const principal = await environment.admin.createPrincipal('stream-transition');
2050
+ const cube = await environment.admin.createCube('stream-transition');
2051
+ await environment.admin.grantCube(principal, cube);
2052
+ const credential = await environment.admin.issueDroneSession(principal);
2053
+ let readCursor!: LogCursor;
2054
+ for (const [index, message] of ['alpha', 'beta', 'gamma'].entries()) {
2055
+ const response = await environment.operations.append(
2056
+ credential,
2057
+ cube,
2058
+ createProtocolEnvelope(`stream-transition-${message}`, {
2059
+ post_id: `00000000-0000-4000-8000-${String(316 + index).padStart(12, '0')}`,
2060
+ to: 'broadcast',
2061
+ message,
2062
+ }),
2063
+ );
2064
+ expectStatus(response, 201, `Stream transition append ${message}`);
2065
+ if (message === 'beta') {
2066
+ const entry = decodeAppendLogResultEnvelope(response.body).payload.entry;
2067
+ readCursor = { id: entry.id, created_at: entry.created_at };
2068
+ }
2069
+ }
2115
2070
  const barrier = environment.admin.armReplayTransition();
2116
- const openPromise = environment.operations.openStream(credentialA, cubeA, readCursor);
2071
+ const openPromise = environment.operations.openStream(credential, cube, readCursor);
2117
2072
  await within(barrier.reached, 'Replay transition boundary', streamDeadlineMs);
2118
2073
  try {
2119
2074
  const appendDelta = environment.operations.append(
2120
- credentialA,
2121
- cubeA,
2122
- createProtocolEnvelope('append-a4', {
2123
- post_id: '00000000-0000-4000-8000-000000000308',
2075
+ credential,
2076
+ cube,
2077
+ createProtocolEnvelope('stream-transition-delta', {
2078
+ post_id: '00000000-0000-4000-8000-000000000319',
2124
2079
  to: 'broadcast',
2125
2080
  message: 'delta',
2126
2081
  }),
@@ -2145,10 +2100,10 @@ export async function runAdapterConformance(
2145
2100
  const noDuplicate = reader.next();
2146
2101
  await provePending(noDuplicate, 'Live stream after delta', pendingProbeMs);
2147
2102
  const epsilonResponse = await environment.operations.append(
2148
- credentialA,
2149
- cubeA,
2150
- createProtocolEnvelope('append-a5', {
2151
- post_id: '00000000-0000-4000-8000-000000000309',
2103
+ credential,
2104
+ cube,
2105
+ createProtocolEnvelope('stream-transition-epsilon', {
2106
+ post_id: '00000000-0000-4000-8000-000000000320',
2152
2107
  to: 'broadcast',
2153
2108
  message: 'epsilon',
2154
2109
  }),
@@ -2158,33 +2113,56 @@ export async function runAdapterConformance(
2158
2113
  invariant(epsilon.entry.message === 'epsilon', 'Live stream duplicated or reordered an event.');
2159
2114
  invariant(compareLogCursor(delta.cursor, epsilon.cursor) < 0, 'Live stream cursors are not ordered.');
2160
2115
  invariant(new Set([replay.entry.id, delta.entry.id, epsilon.entry.id]).size === 3, 'Stream delivered a duplicate entry.');
2161
- liveCursor = epsilon.cursor;
2162
2116
  return { replay: ['gamma'], transition: 'bookmark', live: ['delta', 'epsilon'], duplicates: 0 };
2163
2117
  } finally {
2164
2118
  await reader.close();
2165
2119
  }
2166
2120
  });
2167
-
2168
2121
  await record('cursor.explicit-expiry', async () => {
2169
- invariant(readCursor, 'Cursor fixture did not produce a cursor.');
2170
- await environment.admin.expireCursor(cubeA, readCursor);
2122
+ const cube = await environment.admin.createCube('cursor-expiry');
2123
+ await environment.admin.grantCube(principalA, cube);
2124
+ const appended = await environment.operations.append(
2125
+ credentialA,
2126
+ cube,
2127
+ createProtocolEnvelope('cursor-expiry-entry', {
2128
+ post_id: '00000000-0000-4000-8000-000000000321',
2129
+ to: 'broadcast',
2130
+ message: 'expire this cursor',
2131
+ }),
2132
+ );
2133
+ expectStatus(appended, 201, 'Cursor expiry fixture append');
2134
+ const entry = decodeAppendLogResultEnvelope(appended.body).payload.entry;
2135
+ const cursor = { id: entry.id, created_at: entry.created_at };
2136
+ await environment.admin.expireCursor(cube, cursor);
2171
2137
  const response = await environment.operations.read(
2172
2138
  credentialA,
2173
- cubeA,
2174
- createProtocolEnvelope('read-expired', { cursor: readCursor, limit: 10 }),
2139
+ cube,
2140
+ createProtocolEnvelope('read-expired', { cursor, limit: 10 }),
2175
2141
  );
2176
2142
  expectError(response, 410, ErrorCode.CURSOR_EXPIRED, 'Expired cursor read');
2177
- const stream = await environment.operations.openStream(credentialA, cubeA, readCursor);
2143
+ const stream = await environment.operations.openStream(credentialA, cube, cursor);
2178
2144
  expectError(stream, 410, ErrorCode.CURSOR_EXPIRED, 'Expired cursor stream');
2179
2145
  invariant(stream.stream === null, 'Expired cursor stream exposed a body stream.');
2180
2146
  return { read_status: 410, stream_status: 410, code: ErrorCode.CURSOR_EXPIRED };
2181
2147
  });
2182
2148
 
2183
2149
  await record('acks.idempotent', async () => {
2184
- invariant(entries[0], 'Append fixture did not produce an entry.');
2185
- const request = createProtocolEnvelope('ack-entry1', { entry_id: entries[0].id, kind: 'ack' });
2186
- const first = await environment.operations.ack(credentialA, cubeA, request);
2187
- const second = await environment.operations.ack(credentialA, cubeA, request);
2150
+ const cube = await environment.admin.createCube('ack-idempotency');
2151
+ await environment.admin.grantCube(principalA, cube);
2152
+ const appended = await environment.operations.append(
2153
+ credentialA,
2154
+ cube,
2155
+ createProtocolEnvelope('ack-idempotency-entry', {
2156
+ post_id: '00000000-0000-4000-8000-000000000322',
2157
+ to: 'broadcast',
2158
+ message: 'acknowledge this entry',
2159
+ }),
2160
+ );
2161
+ expectStatus(appended, 201, 'Acknowledgement fixture append');
2162
+ const entry = decodeAppendLogResultEnvelope(appended.body).payload.entry;
2163
+ const request = createProtocolEnvelope('ack-entry1', { entry_id: entry.id, kind: 'ack' });
2164
+ const first = await environment.operations.ack(credentialA, cube, request);
2165
+ const second = await environment.operations.ack(credentialA, cube, request);
2188
2166
  expectStatus(first, 204, 'First acknowledgement');
2189
2167
  expectStatus(second, 204, 'Repeated acknowledgement');
2190
2168
  invariant((first.body === '' || first.body === undefined) && (second.body === '' || second.body === undefined), 'Acknowledgement responses must be bodyless.');
@@ -2215,7 +2193,6 @@ export async function runAdapterConformance(
2215
2193
  expectStatus(append, 201, 'Acknowledgement-status fixture append');
2216
2194
  const entry = decodeAppendLogResultEnvelope(append.body).payload.entry;
2217
2195
 
2218
- const beforeMissing = await environment.admin.observeAuthorityState();
2219
2196
  const missingResponse = await environment.operations.ackStatus(
2220
2197
  credentialA,
2221
2198
  cube,
@@ -2230,13 +2207,6 @@ export async function runAdapterConformance(
2230
2207
  missing.claims.length === 0,
2231
2208
  'Missing acknowledgement was not represented as nullable per-recipient state.',
2232
2209
  );
2233
- assertStateDelta(
2234
- beforeMissing,
2235
- await environment.admin.observeAuthorityState(),
2236
- {},
2237
- 'Missing acknowledgement status query',
2238
- );
2239
-
2240
2210
  expectStatus(
2241
2211
  await environment.operations.ack(
2242
2212
  acknowledgedCredential,
@@ -2255,7 +2225,6 @@ export async function runAdapterConformance(
2255
2225
  204,
2256
2226
  'Acknowledgement-status claim',
2257
2227
  );
2258
- const beforeDistinct = await environment.admin.observeAuthorityState();
2259
2228
  const distinctResponse = await environment.operations.ackStatus(
2260
2229
  credentialA,
2261
2230
  cube,
@@ -2272,26 +2241,6 @@ export async function runAdapterConformance(
2272
2241
  distinct.recipients.find((recipient) => recipient.drone_id === claimingRecipient.id)?.acknowledged_at === null,
2273
2242
  'Acknowledgement status conflated acknowledgement and claim records.',
2274
2243
  );
2275
- assertStateDelta(
2276
- beforeDistinct,
2277
- await environment.admin.observeAuthorityState(),
2278
- {},
2279
- 'Distinct acknowledgement and claim status query',
2280
- );
2281
-
2282
- const unreadResponse = await environment.operations.read(
2283
- credentialA,
2284
- cube,
2285
- createProtocolEnvelope('ack-status-unread', { cursor: null, limit: 10 }),
2286
- );
2287
- expectStatus(unreadResponse, 200, 'Post-query unread read');
2288
- const unread = decodeReadLogResultEnvelope(unreadResponse.body).payload;
2289
- invariant(
2290
- unread.entries.length === 1 && unread.entries[0].id === entry.id,
2291
- 'Acknowledgement-status query advanced unread delivery state.',
2292
- );
2293
-
2294
- const beforeUnknown = await environment.admin.observeAuthorityState();
2295
2244
  expectError(
2296
2245
  await environment.operations.ackStatus(
2297
2246
  credentialA,
@@ -2304,11 +2253,16 @@ export async function runAdapterConformance(
2304
2253
  ErrorCode.NOT_FOUND,
2305
2254
  'Unknown acknowledgement-status entry',
2306
2255
  );
2307
- assertStateDelta(
2308
- beforeUnknown,
2309
- await environment.admin.observeAuthorityState(),
2310
- {},
2311
- 'Unknown acknowledgement status query',
2256
+ const unreadResponse = await environment.operations.read(
2257
+ credentialA,
2258
+ cube,
2259
+ createProtocolEnvelope('ack-status-unread', { cursor: null, limit: 10 }),
2260
+ );
2261
+ expectStatus(unreadResponse, 200, 'Post-query unread read');
2262
+ const unread = decodeReadLogResultEnvelope(unreadResponse.body).payload;
2263
+ invariant(
2264
+ same(unread.entries, [entry]),
2265
+ 'Acknowledgement-status query mutated or advanced unread delivery state.',
2312
2266
  );
2313
2267
  return {
2314
2268
  missing_acknowledgement: null,
@@ -2321,23 +2275,38 @@ export async function runAdapterConformance(
2321
2275
  });
2322
2276
 
2323
2277
  await record('claims.durable-noncursor', async () => {
2324
- invariant(entries[1] && liveCursor, 'Log fixtures did not produce claim state.');
2278
+ const principal = await environment.admin.createPrincipal('claim-noncursor');
2279
+ const cube = await environment.admin.createCube('claim-noncursor');
2280
+ await environment.admin.grantCube(principal, cube);
2281
+ const credential = await environment.admin.issueDroneSession(principal);
2282
+ const appended = await environment.operations.append(
2283
+ credential,
2284
+ cube,
2285
+ createProtocolEnvelope('claim-fixture-entry', {
2286
+ post_id: '00000000-0000-4000-8000-000000000314',
2287
+ to: 'broadcast',
2288
+ message: 'claim cursor baseline',
2289
+ }),
2290
+ );
2291
+ expectStatus(appended, 201, 'Claim fixture append');
2292
+ const entry = decodeAppendLogResultEnvelope(appended.body).payload.entry;
2293
+ const baselineCursor = { id: entry.id, created_at: entry.created_at };
2325
2294
  const claim = await environment.operations.ack(
2326
- credentialA,
2327
- cubeA,
2328
- createProtocolEnvelope('claim-entry2', { entry_id: entries[1].id, kind: 'claim' }),
2295
+ credential,
2296
+ cube,
2297
+ createProtocolEnvelope('claim-fixture-claim', { entry_id: entry.id, kind: 'claim' }),
2329
2298
  );
2330
2299
  expectStatus(claim, 204, 'Claim');
2331
2300
  const read = await environment.operations.read(
2332
- credentialA,
2333
- cubeA,
2334
- createProtocolEnvelope('read-claims', { cursor: liveCursor, limit: 10 }),
2301
+ credential,
2302
+ cube,
2303
+ createProtocolEnvelope('claim-fixture-readback', { cursor: baselineCursor, limit: 10 }),
2335
2304
  );
2336
2305
  expectStatus(read, 200, 'Claim-state read');
2337
2306
  const page = decodeReadLogResultEnvelope(read.body).payload;
2338
2307
  invariant(page.entries.length === 0, 'Claim unexpectedly created a log entry.');
2339
- invariant(page.cursor !== null && compareLogCursor(page.cursor, liveCursor) === 0, 'Claim advanced the log cursor.');
2340
- invariant(page.claims.some((item) => item.log_entry_id === entries[1].id), 'Claim was not durable in a later read.');
2308
+ invariant(page.cursor !== null && compareLogCursor(page.cursor, baselineCursor) === 0, 'Claim advanced the log cursor.');
2309
+ invariant(page.claims.some((item) => item.log_entry_id === entry.id), 'Claim was not durable in a later read.');
2341
2310
  return { durable_claims: 1, entries: 0, cursor_advanced: false };
2342
2311
  });
2343
2312
 
@@ -2378,6 +2347,7 @@ export async function runAdapterConformance(
2378
2347
  let metadataDroneB!: ConformanceDrone;
2379
2348
  let metadataSessionA = '';
2380
2349
  await record('security.drone-management-authorization', async () => {
2350
+ const observationCredential = await environment.admin.issueDroneSession(principalA);
2381
2351
  workerRoleA = await environment.admin.createRole(cubeA, {
2382
2352
  roleClass: 'worker', isHumanSeat: false,
2383
2353
  });
@@ -2404,6 +2374,10 @@ export async function runAdapterConformance(
2404
2374
  deniedCredentials.push({ access: access as 'read' | 'write', credential });
2405
2375
  }
2406
2376
  for (const { access, credential } of deniedCredentials) {
2377
+ const rosterBefore = await environment.operations.listDrones(observationCredential, cubeA);
2378
+ expectStatus(rosterBefore, 200, `${access} principal pre-denial roster`);
2379
+ const workerBefore = listedDrone(rosterBefore, managedWorker.id);
2380
+ invariant(workerBefore, `${access} principal pre-denial roster omitted the managed worker.`);
2407
2381
  expectError(
2408
2382
  await environment.operations.reassignDrone(
2409
2383
  credential,
@@ -2426,10 +2400,15 @@ export async function runAdapterConformance(
2426
2400
  ErrorCode.ACCESS_DENIED,
2427
2401
  `${access} principal eviction`,
2428
2402
  );
2403
+ const rosterAfter = await environment.operations.listDrones(observationCredential, cubeA);
2404
+ expectStatus(rosterAfter, 200, `${access} principal post-denial roster`);
2405
+ invariant(
2406
+ same(listedDrone(rosterAfter, managedWorker.id), workerBefore),
2407
+ `${access} principal management denial mutated the managed worker.`,
2408
+ );
2429
2409
  }
2430
2410
  return { read_status: 403, write_status: 403, manage_required: true };
2431
2411
  });
2432
-
2433
2412
  await record('security.manage-access-matrix', async () => {
2434
2413
  const noGrantPrincipal = await environment.admin.createPrincipal('Coordinator role without cube grant');
2435
2414
  const noGrantInvitation = await environment.admin.issueSingleUseInvitation(noGrantPrincipal, 'client');
@@ -2449,12 +2428,8 @@ export async function runAdapterConformance(
2449
2428
  roleClass: 'worker', isHumanSeat: false,
2450
2429
  });
2451
2430
  const evictionTarget = await environment.admin.createDrone(principalA, cubeA, workerRoleA);
2452
- await environment.admin.issueManagedDroneSession(evictionTarget);
2431
+ const evictionTargetCredential = await environment.admin.issueManagedDroneSession(evictionTarget);
2453
2432
  const unknownCube = { id: '00000000-0000-4000-8000-000000000399' };
2454
- const snapshot = async (): Promise<unknown> => ({
2455
- cubeA: await environment.admin.inspectCubeManagementState(cubeA),
2456
- cubeB: await environment.admin.inspectCubeManagementState(cubeB),
2457
- });
2458
2433
  const operations: ReadonlyArray<{
2459
2434
  name: string;
2460
2435
  successStatus: number;
@@ -2519,6 +2494,48 @@ export async function runAdapterConformance(
2519
2494
  ),
2520
2495
  },
2521
2496
  ];
2497
+ const observableState = async (operationName: string): Promise<unknown | null> => {
2498
+ if (operationName === 'decision-record') {
2499
+ const response = await environment.operations.listDecisions(
2500
+ credentialA,
2501
+ cubeA,
2502
+ createProtocolEnvelope('matrix-observe-decisions', {}),
2503
+ );
2504
+ expectStatus(response, 200, 'Matrix decision observation');
2505
+ return decodeDecisionsResultEnvelope(response.body).payload;
2506
+ }
2507
+ if (operationName === 'drone-reassign' || operationName === 'drone-evict') {
2508
+ const response = await environment.operations.listDrones(credentialA, cubeA);
2509
+ expectStatus(response, 200, 'Matrix drone observation');
2510
+ return listedDrone(
2511
+ response,
2512
+ operationName === 'drone-reassign' ? managedWorker.id : evictionTarget.id,
2513
+ );
2514
+ }
2515
+ return null;
2516
+ };
2517
+ const assertObservableDenial = async (operationName: string, before: unknown | null): Promise<void> => {
2518
+ if (operationName === 'role-create') {
2519
+ expectError(
2520
+ await environment.operations.roleRationale(
2521
+ credentialA,
2522
+ cubeA,
2523
+ createProtocolEnvelope('matrix-observe-role', {
2524
+ role: 'Matrix Role',
2525
+ section: 'Workflow rationale',
2526
+ }),
2527
+ ),
2528
+ 404,
2529
+ ErrorCode.ROLE_NOT_FOUND,
2530
+ 'Denied matrix role observation',
2531
+ );
2532
+ } else if (before !== null) {
2533
+ invariant(
2534
+ same(await observableState(operationName), before),
2535
+ `${operationName} changed protocol-visible state after denial.`,
2536
+ );
2537
+ }
2538
+ };
2522
2539
 
2523
2540
  for (const operation of operations) {
2524
2541
  for (const [kind, credential] of [
@@ -2526,14 +2543,25 @@ export async function runAdapterConformance(
2526
2543
  ['write', writeCredential],
2527
2544
  ['drone-session', droneCredential],
2528
2545
  ] as const) {
2529
- const before = await snapshot();
2546
+ const before = await observableState(operation.name);
2530
2547
  expectError(
2531
2548
  await operation.invoke(credential, cubeA),
2532
2549
  403,
2533
2550
  ErrorCode.ACCESS_DENIED,
2534
2551
  `${operation.name} by ${kind} principal`,
2535
2552
  );
2536
- invariant(same(await snapshot(), before), `${operation.name} mutated state after ${kind} denial.`);
2553
+ await assertObservableDenial(operation.name, before);
2554
+ if (operation.name === 'drone-evict') {
2555
+ expectStatus(
2556
+ await environment.operations.read(
2557
+ evictionTargetCredential,
2558
+ cubeA,
2559
+ createProtocolEnvelope(`matrix-${kind}-eviction-target-probe`, { cursor: null, limit: 1 }),
2560
+ ),
2561
+ 200,
2562
+ `${kind} denied eviction target probe`,
2563
+ );
2564
+ }
2537
2565
  }
2538
2566
  for (const [kind, credential, cube] of [
2539
2567
  ['no-grant', noGrantCredential, cubeA],
@@ -2541,22 +2569,28 @@ export async function runAdapterConformance(
2541
2569
  ['foreign-cube', credentialA, cubeB],
2542
2570
  ['unknown-cube', credentialA, unknownCube],
2543
2571
  ] as const) {
2544
- const before = await snapshot();
2572
+ const before = await observableState(operation.name);
2545
2573
  expectError(
2546
2574
  await operation.invoke(credential, cube),
2547
2575
  404,
2548
2576
  ErrorCode.NOT_FOUND,
2549
2577
  `${operation.name} against ${kind}`,
2550
2578
  );
2551
- invariant(same(await snapshot(), before), `${operation.name} mutated state after ${kind} denial.`);
2579
+ await assertObservableDenial(operation.name, before);
2580
+ if (operation.name === 'drone-evict') {
2581
+ expectStatus(
2582
+ await environment.operations.read(
2583
+ evictionTargetCredential,
2584
+ cubeA,
2585
+ createProtocolEnvelope(`matrix-${kind}-eviction-target-probe`, { cursor: null, limit: 1 }),
2586
+ ),
2587
+ 200,
2588
+ `${kind} denied eviction target probe`,
2589
+ );
2590
+ }
2552
2591
  }
2553
- const beforeSuccess = await environment.admin.inspectCubeManagementState(cubeA);
2554
2592
  const success = await operation.invoke(credentialA, cubeA);
2555
2593
  expectStatus(success, operation.successStatus, `${operation.name} by managing principal`);
2556
- invariant(
2557
- !same(await environment.admin.inspectCubeManagementState(cubeA), beforeSuccess),
2558
- `${operation.name} managing success did not mutate its declared state.`,
2559
- );
2560
2594
  }
2561
2595
  return {
2562
2596
  operation_count: operations.length,
@@ -2564,7 +2598,8 @@ export async function runAdapterConformance(
2564
2598
  read_write_status: 403,
2565
2599
  drone_session_status: 403,
2566
2600
  hidden_status: 404,
2567
- denied_mutations: 0,
2601
+ observable_non_mutation_operations: 4,
2602
+ write_only_operations: 2,
2568
2603
  role_labels_authoritative: false,
2569
2604
  };
2570
2605
  });
@@ -2651,12 +2686,18 @@ export async function runAdapterConformance(
2651
2686
  occupied_human_seat_denied: true,
2652
2687
  };
2653
2688
  });
2654
-
2655
2689
  await record('security.cross-cube-drone-management', async () => {
2656
2690
  const foreignRole = await environment.admin.createRole(cubeB, {
2657
2691
  roleClass: 'worker', isHumanSeat: false,
2658
2692
  });
2659
2693
  const foreignDrone = await environment.admin.createDrone(principalB, cubeB, foreignRole);
2694
+ const foreignRosterBefore = await environment.operations.listDrones(credentialB, cubeB);
2695
+ const localRosterBefore = await environment.operations.listDrones(credentialA, cubeA);
2696
+ expectStatus(foreignRosterBefore, 200, 'Pre-denial foreign roster');
2697
+ expectStatus(localRosterBefore, 200, 'Pre-denial local roster');
2698
+ const foreignDroneBefore = listedDrone(foreignRosterBefore, foreignDrone.id);
2699
+ const managedWorkerBefore = listedDrone(localRosterBefore, managedWorker.id);
2700
+ invariant(foreignDroneBefore && managedWorkerBefore, 'Pre-denial roster omitted a drone-management target.');
2660
2701
  expectError(
2661
2702
  await environment.operations.reassignDrone(
2662
2703
  credentialA,
@@ -2713,7 +2754,6 @@ export async function runAdapterConformance(
2713
2754
  'Foreign role reassignment through authorized cube route',
2714
2755
  );
2715
2756
  await environment.admin.grantCube(principalA, cubeB, 'read');
2716
- const foreignDroneBefore = await environment.admin.inspectManagedDrone(foreignDrone);
2717
2757
  expectError(
2718
2758
  await environment.operations.reassignDrone(
2719
2759
  workerSession,
@@ -2725,10 +2765,6 @@ export async function runAdapterConformance(
2725
2765
  ErrorCode.NOT_FOUND,
2726
2766
  'Bound drone cross-cube reassignment',
2727
2767
  );
2728
- invariant(
2729
- same(await environment.admin.inspectManagedDrone(foreignDrone), foreignDroneBefore),
2730
- 'Bound drone cross-cube reassignment mutated the foreign target.',
2731
- );
2732
2768
  expectError(
2733
2769
  await environment.operations.evictDrone(
2734
2770
  workerSession,
@@ -2740,15 +2776,24 @@ export async function runAdapterConformance(
2740
2776
  ErrorCode.NOT_FOUND,
2741
2777
  'Bound drone cross-cube eviction',
2742
2778
  );
2779
+ const foreignRosterAfter = await environment.operations.listDrones(credentialB, cubeB);
2780
+ const localRosterAfter = await environment.operations.listDrones(credentialA, cubeA);
2781
+ expectStatus(foreignRosterAfter, 200, 'Post-denial foreign roster');
2782
+ expectStatus(localRosterAfter, 200, 'Post-denial local roster');
2743
2783
  invariant(
2744
- same(await environment.admin.inspectManagedDrone(foreignDrone), foreignDroneBefore),
2745
- 'Bound drone cross-cube eviction mutated the foreign target.',
2784
+ same(listedDrone(foreignRosterAfter, foreignDrone.id), foreignDroneBefore),
2785
+ 'Denied cross-cube management mutated the foreign drone.',
2786
+ );
2787
+ invariant(
2788
+ same(listedDrone(localRosterAfter, managedWorker.id), managedWorkerBefore),
2789
+ 'Denied foreign-role management mutated the local drone.',
2746
2790
  );
2747
2791
  return {
2748
2792
  unauthorized_cube_status: 404,
2749
2793
  foreign_drone_status: 404,
2750
2794
  foreign_role_status: 404,
2751
2795
  bound_drone_cross_cube_status: 404,
2796
+ targets_unchanged: true,
2752
2797
  code: ErrorCode.NOT_FOUND,
2753
2798
  };
2754
2799
  });
@@ -2783,14 +2828,6 @@ export async function runAdapterConformance(
2783
2828
  }),
2784
2829
  'Eviction response did not identify the terminal seat.',
2785
2830
  );
2786
- invariant(
2787
- same(await environment.admin.inspectManagedDrone(evictedDrone), {
2788
- role_id: workerRoleA.id,
2789
- evicted: true,
2790
- session_revoked: true,
2791
- }),
2792
- 'Eviction did not atomically mark the drone evicted and revoke its session.',
2793
- );
2794
2831
  const after = await environment.operations.listDrones(credentialA, cubeA);
2795
2832
  expectStatus(after, 200, 'Post-eviction roster');
2796
2833
  invariant(!listedDroneIds(after).includes(evictedDrone.id), 'Evicted drone remained in roster.');
@@ -2864,38 +2901,46 @@ export async function runAdapterConformance(
2864
2901
  },
2865
2902
  )), 201, 'Role-contract reader enrollment');
2866
2903
 
2904
+ const refusalRationale = 'Workflow rationale:\nRefusal role remains.';
2867
2905
  const defaultRole = await environment.admin.createRole(roleContractCube, {
2868
2906
  roleClass: 'worker',
2869
2907
  isHumanSeat: false,
2870
2908
  name: 'Default Worker',
2909
+ detailedDescription: refusalRationale,
2871
2910
  isDefault: true,
2872
2911
  });
2873
2912
  const mandatoryRole = await environment.admin.createRole(roleContractCube, {
2874
2913
  roleClass: 'worker',
2875
2914
  isHumanSeat: false,
2876
2915
  name: 'Mandatory Worker',
2916
+ detailedDescription: refusalRationale,
2877
2917
  isMandatory: true,
2878
2918
  });
2879
2919
  const humanRole = await environment.admin.createRole(roleContractCube, {
2880
2920
  roleClass: 'queen',
2881
2921
  isHumanSeat: true,
2882
2922
  name: 'Human Seat',
2923
+ detailedDescription: refusalRationale,
2883
2924
  });
2884
2925
  const activeRole = await environment.admin.createRole(roleContractCube, {
2885
2926
  roleClass: 'worker',
2886
2927
  isHumanSeat: false,
2887
2928
  name: 'Active Worker',
2929
+ detailedDescription: refusalRationale,
2888
2930
  });
2889
- await environment.admin.createDrone(roleContractPrincipal, roleContractCube, activeRole);
2931
+ const activeDrone = await environment.admin.createDrone(roleContractPrincipal, roleContractCube, activeRole);
2932
+ const activeRosterBefore = await environment.operations.listDrones(roleContractCredential, roleContractCube);
2933
+ expectStatus(activeRosterBefore, 200, 'Pre-refusal active-role roster');
2934
+ const activeDroneBefore = listedDrone(activeRosterBefore, activeDrone.id);
2935
+ invariant(activeDroneBefore, 'Pre-refusal roster omitted the active-role drone.');
2890
2936
 
2891
2937
  const refusals = [
2892
- [defaultRole, ErrorCode.DEFAULT_ROLE_REQUIRED, 'default role'],
2893
- [mandatoryRole, ErrorCode.ROLE_REQUIRED, 'mandatory role'],
2894
- [humanRole, ErrorCode.ROLE_REQUIRED, 'human-seat role'],
2895
- [activeRole, ErrorCode.ROLE_IN_USE, 'active-drone role'],
2938
+ [defaultRole, ErrorCode.DEFAULT_ROLE_REQUIRED, 'default role', 'Default Worker', 'worker', false],
2939
+ [mandatoryRole, ErrorCode.ROLE_REQUIRED, 'mandatory role', 'Mandatory Worker', 'worker', false],
2940
+ [humanRole, ErrorCode.ROLE_REQUIRED, 'human-seat role', 'Human Seat', 'queen', true],
2941
+ [activeRole, ErrorCode.ROLE_IN_USE, 'active-drone role', 'Active Worker', 'worker', false],
2896
2942
  ] as const;
2897
- for (const [index, [role, code, label]] of refusals.entries()) {
2898
- const before = await environment.admin.inspectCubeManagementState(roleContractCube);
2943
+ for (const [index, [role, code, label, roleName, roleClass, isHumanSeat]] of refusals.entries()) {
2899
2944
  const response = await environment.operations.deleteRole(
2900
2945
  roleContractCredential,
2901
2946
  roleContractCube,
@@ -2903,17 +2948,65 @@ export async function runAdapterConformance(
2903
2948
  createProtocolEnvelope(`delete-refusal-${index}`, {}),
2904
2949
  );
2905
2950
  expectError(response, 409, code, `Delete ${label}`);
2906
- invariant(
2907
- same(await environment.admin.inspectCubeManagementState(roleContractCube), before),
2908
- `Delete ${label} mutated cube state after refusal.`,
2909
- );
2910
2951
  if (code === ErrorCode.ROLE_IN_USE) {
2911
2952
  const message = protocolErrorMessage(response) ?? '';
2912
2953
  invariant(
2913
2954
  message === ROLE_IN_USE_DELETE_MESSAGE,
2914
2955
  'ROLE_IN_USE did not direct the caller to reassign or evict the drones first.',
2915
2956
  );
2957
+ const roster = await environment.operations.listDrones(roleContractCredential, roleContractCube);
2958
+ expectStatus(roster, 200, 'Active-role refusal roster readback');
2959
+ invariant(
2960
+ same(listedDrone(roster, activeDrone.id), activeDroneBefore),
2961
+ 'Active-role deletion refusal changed the active drone.',
2962
+ );
2916
2963
  }
2964
+ const retained = await environment.operations.roleRationale(
2965
+ roleContractReadCredential,
2966
+ roleContractCube,
2967
+ createProtocolEnvelope(`delete-refusal-${index}-readback`, {
2968
+ role: role.id,
2969
+ section: 'Workflow rationale',
2970
+ }),
2971
+ );
2972
+ expectStatus(retained, 200, `Retained ${label} rationale lookup`);
2973
+ const retainedPayload = decodeRoleRationaleResultEnvelope(retained.body).payload;
2974
+ invariant(
2975
+ retainedPayload.role_id === role.id &&
2976
+ retainedPayload.role_name === roleName &&
2977
+ same(retainedPayload.section, {
2978
+ heading: 'Workflow rationale',
2979
+ body: refusalRationale,
2980
+ }),
2981
+ `Retained ${label} rationale lookup returned a different role or section.`,
2982
+ );
2983
+ const shapeSession = `${String(index).repeat(42)}S`;
2984
+ const shapeProbe = await environment.operations.attach(
2985
+ roleContractCredential,
2986
+ createProtocolEnvelope(`delete-refusal-${index}-shape-probe`, {
2987
+ cube_id: roleContractCube.id,
2988
+ role_id: role.id,
2989
+ session_credential: shapeSession,
2990
+ }),
2991
+ );
2992
+ expectStatus(shapeProbe, 200, `Retained ${label} shape probe`);
2993
+ const shapePayload = decodeAttachResponseEnvelope(shapeProbe.body).payload;
2994
+ invariant(
2995
+ shapePayload.role.id === role.id &&
2996
+ shapePayload.role.role_class === roleClass &&
2997
+ shapePayload.role.is_human_seat === isHumanSeat,
2998
+ `Retained ${label} shape probe returned changed role semantics.`,
2999
+ );
3000
+ expectStatus(
3001
+ await environment.operations.evictDrone(
3002
+ roleContractCredential,
3003
+ roleContractCube,
3004
+ { id: shapePayload.drone.id },
3005
+ createProtocolEnvelope(`delete-refusal-${index}-shape-cleanup`, {}),
3006
+ ),
3007
+ 200,
3008
+ `Retained ${label} shape cleanup`,
3009
+ );
2917
3010
  }
2918
3011
 
2919
3012
  const unknownRole = { id: '00000000-0000-4000-8000-000000000398' };
@@ -2933,8 +3026,8 @@ export async function runAdapterConformance(
2933
3026
  roleClass: 'worker',
2934
3027
  isHumanSeat: false,
2935
3028
  name: 'Disposable Worker',
3029
+ detailedDescription: refusalRationale,
2936
3030
  });
2937
- const beforeReadDenial = await environment.admin.inspectCubeManagementState(roleContractCube);
2938
3031
  expectError(
2939
3032
  await environment.operations.deleteRole(
2940
3033
  roleContractReadCredential,
@@ -2946,12 +3039,50 @@ export async function runAdapterConformance(
2946
3039
  ErrorCode.ACCESS_DENIED,
2947
3040
  'Delete role with read authority',
2948
3041
  );
3042
+ const retainedDeletable = await environment.operations.roleRationale(
3043
+ roleContractReadCredential,
3044
+ roleContractCube,
3045
+ createProtocolEnvelope('delete-role-read-denied-readback', {
3046
+ role: deletableRole.id,
3047
+ section: 'Workflow rationale',
3048
+ }),
3049
+ );
3050
+ expectStatus(retainedDeletable, 200, 'Read-denied retained role rationale lookup');
3051
+ const retainedDeletablePayload = decodeRoleRationaleResultEnvelope(retainedDeletable.body).payload;
2949
3052
  invariant(
2950
- same(
2951
- await environment.admin.inspectCubeManagementState(roleContractCube),
2952
- beforeReadDenial,
3053
+ retainedDeletablePayload.role_id === deletableRole.id &&
3054
+ retainedDeletablePayload.role_name === 'Disposable Worker' &&
3055
+ same(retainedDeletablePayload.section, {
3056
+ heading: 'Workflow rationale',
3057
+ body: refusalRationale,
3058
+ }),
3059
+ 'Read-authority deletion denial changed the target role.',
3060
+ );
3061
+ const shapeProbe = await environment.operations.attach(
3062
+ roleContractCredential,
3063
+ createProtocolEnvelope('delete-role-read-denied-shape-probe', {
3064
+ cube_id: roleContractCube.id,
3065
+ role_id: deletableRole.id,
3066
+ session_credential: 'S'.repeat(43),
3067
+ }),
3068
+ );
3069
+ expectStatus(shapeProbe, 200, 'Read-denied retained role shape probe');
3070
+ const shapePayload = decodeAttachResponseEnvelope(shapeProbe.body).payload;
3071
+ invariant(
3072
+ shapePayload.role.id === deletableRole.id &&
3073
+ shapePayload.role.role_class === 'worker' &&
3074
+ shapePayload.role.is_human_seat === false,
3075
+ 'Read-authority deletion denial changed the target role shape.',
3076
+ );
3077
+ expectStatus(
3078
+ await environment.operations.evictDrone(
3079
+ roleContractCredential,
3080
+ roleContractCube,
3081
+ { id: shapePayload.drone.id },
3082
+ createProtocolEnvelope('delete-role-read-denied-shape-cleanup', {}),
2953
3083
  ),
2954
- 'Read-authority role deletion mutated cube state.',
3084
+ 200,
3085
+ 'Read-denied retained role shape cleanup',
2955
3086
  );
2956
3087
  const deleted = await environment.operations.deleteRole(
2957
3088
  roleContractCredential,
@@ -3002,10 +3133,6 @@ export async function runAdapterConformance(
3002
3133
  evictedRole,
3003
3134
  createProtocolEnvelope('delete-evicted-role', {}),
3004
3135
  ), 200, 'Delete role held only by an evicted drone');
3005
- invariant(
3006
- (await environment.admin.inspectManagedDrone(evictedDrone)).role_id === defaultRole.id,
3007
- 'Role deletion did not retarget the evicted drone to the surviving default role.',
3008
- );
3009
3136
  const read = await environment.operations.read(
3010
3137
  roleContractCredential,
3011
3138
  roleContractCube,
@@ -3028,11 +3155,10 @@ export async function runAdapterConformance(
3028
3155
  ErrorCode.ROLE_REQUIRED,
3029
3156
  ],
3030
3157
  in_use_message_actionable: true,
3031
- evicted_drone_retargeted: true,
3158
+ refusals_non_mutating: true,
3032
3159
  activity_log_attribution_preserved: true,
3033
3160
  };
3034
3161
  });
3035
-
3036
3162
  await record('roles.rationale-contract', async () => {
3037
3163
  const detailedDescription = [
3038
3164
  'Implements assigned work.',
@@ -3122,24 +3248,25 @@ export async function runAdapterConformance(
3122
3248
  name: 'Ambiguous Role',
3123
3249
  detailedDescription,
3124
3250
  });
3125
- await environment.admin.createRole(roleContractCube, {
3126
- roleClass: 'worker',
3127
- isHumanSeat: false,
3128
- name: 'AMBIGUOUS ROLE',
3129
- detailedDescription,
3130
- });
3131
3251
  expectError(
3132
- await environment.operations.roleRationale(
3133
- roleContractReadCredential,
3252
+ await environment.operations.createRole(
3253
+ roleContractCredential,
3134
3254
  roleContractCube,
3135
- createProtocolEnvelope('rationale-ambiguous-role', {
3136
- role: 'ambiguous role',
3137
- section: 'Workflow rationale',
3138
- }),
3255
+ createProtocolEnvelope('role-case-variant-duplicate', { name: 'AMBIGUOUS ROLE' }),
3256
+ ),
3257
+ 409,
3258
+ ErrorCode.INVALID_INPUT,
3259
+ 'Case-variant duplicate role name',
3260
+ );
3261
+ expectError(
3262
+ await environment.operations.createRole(
3263
+ roleContractCredential,
3264
+ roleContractCube,
3265
+ createProtocolEnvelope('role-invalid-character', { name: 'Invalid/Role' }),
3139
3266
  ),
3140
3267
  400,
3141
3268
  ErrorCode.INVALID_INPUT,
3142
- 'Ambiguous role rationale lookup',
3269
+ 'Invalid role name character',
3143
3270
  );
3144
3271
  expectError(
3145
3272
  await environment.operations.roleRationale(
@@ -3162,7 +3289,8 @@ export async function runAdapterConformance(
3162
3289
  unknown_role_code: ErrorCode.ROLE_NOT_FOUND,
3163
3290
  inaccessible_role_code: ErrorCode.ROLE_NOT_FOUND,
3164
3291
  unknown_section_code: ErrorCode.ROLE_SECTION_NOT_FOUND,
3165
- ambiguous_role_code: ErrorCode.INVALID_INPUT,
3292
+ case_variant_duplicate_status: 409,
3293
+ invalid_name_code: ErrorCode.INVALID_INPUT,
3166
3294
  invalid_selector_code: ErrorCode.INVALID_INPUT,
3167
3295
  };
3168
3296
  });
@@ -3173,14 +3301,20 @@ export async function runAdapterConformance(
3173
3301
  working_repo_name: 'Byte-Ventures/borg-mcp',
3174
3302
  working_repo_origin: 'https://github.com/Byte-Ventures/borg-mcp',
3175
3303
  };
3304
+ try {
3305
+ metadataDroneA = await environment.admin.createDrone(principalA, cubeA, workerRoleA);
3306
+ metadataSessionA = await environment.admin.issueManagedDroneSession(metadataDroneA);
3307
+ } catch (error) {
3308
+ prerequisiteFailures.set('shared.metadata-baseline', error instanceof Error ? error.message : String(error));
3309
+ }
3176
3310
  await record('metadata.attach-report', async () => {
3177
- metadataSessionA = 'M'.repeat(43);
3311
+ const attachSession = 'M'.repeat(43);
3178
3312
  const created = await environment.operations.attach(
3179
3313
  credentialA,
3180
3314
  createProtocolEnvelope('metadata-attach-created', {
3181
3315
  cube_id: cubeA.id,
3182
3316
  role_id: workerRoleA.id,
3183
- session_credential: metadataSessionA,
3317
+ session_credential: attachSession,
3184
3318
  runtime_metadata: {
3185
3319
  ...knownMetadata,
3186
3320
  working_repo_origin: 'git@github.com:Byte-Ventures/borg-mcp.git',
@@ -3192,7 +3326,7 @@ export async function runAdapterConformance(
3192
3326
  invariant(createdPayload.result === 'created', 'First metadata attach did not create a seat.');
3193
3327
  invariant(same(createdPayload.drone.runtime_metadata, knownMetadata), 'Attach did not echo canonical metadata.');
3194
3328
  invariant(createdPayload.drone.runtime_metadata_reported, 'Present attach report was not marked reported.');
3195
- metadataDroneA = { id: createdPayload.drone.id };
3329
+ const attachedDrone = { id: createdPayload.drone.id };
3196
3330
 
3197
3331
  const unavailableSession = 'N'.repeat(43);
3198
3332
  const unavailable = await environment.operations.attach(
@@ -3239,15 +3373,15 @@ export async function runAdapterConformance(
3239
3373
  createProtocolEnvelope('metadata-attach-reused', {
3240
3374
  cube_id: cubeA.id,
3241
3375
  role_id: workerRoleA.id,
3242
- prior_drone_id: metadataDroneA.id,
3243
- session_credential: metadataSessionA,
3376
+ prior_drone_id: attachedDrone.id,
3377
+ session_credential: attachSession,
3244
3378
  runtime_metadata: knownMetadata,
3245
3379
  }),
3246
3380
  );
3247
3381
  expectStatus(reused, 200, 'Metadata attach reuse');
3248
3382
  invariant(decodeAttachResponseEnvelope(reused.body).payload.result === 'reused', 'Prior seat was not reused.');
3249
3383
  const cleared = await environment.operations.selfMetadataUpdate(
3250
- metadataSessionA,
3384
+ attachSession,
3251
3385
  cubeA,
3252
3386
  createProtocolEnvelope('metadata-clear-all', {
3253
3387
  agent_kind: null,
@@ -3265,7 +3399,7 @@ export async function runAdapterConformance(
3265
3399
  );
3266
3400
  expectStatus(
3267
3401
  await environment.operations.selfMetadataUpdate(
3268
- metadataSessionA,
3402
+ attachSession,
3269
3403
  cubeA,
3270
3404
  createProtocolEnvelope('metadata-restore-known', knownMetadata),
3271
3405
  ),
@@ -3283,7 +3417,6 @@ export async function runAdapterConformance(
3283
3417
  canonical_response: true,
3284
3418
  };
3285
3419
  });
3286
-
3287
3420
  await record('metadata.self-heal-patch', async () => {
3288
3421
  const updates = [
3289
3422
  { request_id: 'metadata-known-new', patch: { reported_model: 'openai/gpt-5.6-terra' } },
@@ -3291,6 +3424,7 @@ export async function runAdapterConformance(
3291
3424
  { request_id: 'metadata-null-repeat', patch: { reported_model: null } },
3292
3425
  { request_id: 'metadata-same-value', patch: { agent_kind: 'opencode' as const } },
3293
3426
  ];
3427
+ let state;
3294
3428
  for (const update of updates) {
3295
3429
  const response = await environment.operations.selfMetadataUpdate(
3296
3430
  metadataSessionA,
@@ -3298,15 +3432,30 @@ export async function runAdapterConformance(
3298
3432
  createProtocolEnvelope(update.request_id, update.patch),
3299
3433
  );
3300
3434
  expectStatus(response, 200, update.request_id);
3301
- decodeUpdateDroneRuntimeMetadataResponseEnvelope(response.body);
3435
+ state = decodeUpdateDroneRuntimeMetadataResponseEnvelope(response.body).payload;
3302
3436
  }
3303
- const state = await environment.admin.inspectDroneRuntimeState(metadataDroneA);
3304
- invariant(state.metadata.reported_model === null, 'Explicit null did not clear model metadata.');
3305
- invariant(state.metadata.agent_kind === 'opencode', 'Omitted field was not preserved.');
3437
+ invariant(state?.runtime_metadata.reported_model === null, 'Explicit null did not clear model metadata.');
3438
+ invariant(state.runtime_metadata.agent_kind === 'opencode', 'Omitted field was not preserved.');
3306
3439
  return { known_replace: true, omitted_unchanged: true, null_clear: true, repeat_safe: true };
3307
3440
  });
3308
3441
 
3309
3442
  await record('security.metadata-invalid-atomic', async () => {
3443
+ const baselineResponse = await environment.operations.selfMetadataUpdate(
3444
+ metadataSessionA,
3445
+ cubeA,
3446
+ createProtocolEnvelope('metadata-invalid-baseline', {
3447
+ agent_kind: 'opencode',
3448
+ reported_model: null,
3449
+ working_repo_name: 'Byte-Ventures/borg-mcp-shared',
3450
+ working_repo_origin: 'https://github.com/Byte-Ventures/borg-mcp-shared',
3451
+ }),
3452
+ );
3453
+ expectStatus(baselineResponse, 200, 'Invalid metadata baseline');
3454
+ decodeUpdateDroneRuntimeMetadataResponseEnvelope(baselineResponse.body);
3455
+ const baselineRoster = await environment.operations.listDrones(credentialA, cubeA);
3456
+ expectStatus(baselineRoster, 200, 'Invalid metadata baseline roster');
3457
+ const baselineDrone = listedDrone(baselineRoster, metadataDroneA.id);
3458
+ invariant(baselineDrone, 'Invalid metadata baseline roster omitted the metadata seat.');
3310
3459
  const invalidPatches: unknown[] = [
3311
3460
  {},
3312
3461
  { agent_kind: 'OpenCode' },
@@ -3324,15 +3473,16 @@ export async function runAdapterConformance(
3324
3473
  { last_seen: '2026-07-14T10:00:00.000Z' },
3325
3474
  ];
3326
3475
  for (const [index, patch] of invalidPatches.entries()) {
3327
- const before = await environment.admin.inspectDroneRuntimeState(metadataDroneA);
3328
3476
  const response = await environment.operations.selfMetadataUpdate(
3329
3477
  metadataSessionA,
3330
3478
  cubeA,
3331
3479
  createProtocolEnvelope(`metadata-invalid-${index}`, patch),
3332
3480
  );
3333
3481
  expectError(response, 400, ErrorCode.INVALID_INPUT, `Invalid metadata patch ${index}`);
3482
+ const readbackResponse = await environment.operations.listDrones(credentialA, cubeA);
3483
+ expectStatus(readbackResponse, 200, `Invalid metadata readback ${index}`);
3334
3484
  invariant(
3335
- same(await environment.admin.inspectDroneRuntimeState(metadataDroneA), before),
3485
+ same(listedDrone(readbackResponse, metadataDroneA.id), baselineDrone),
3336
3486
  `Invalid metadata patch ${index} partially mutated state.`,
3337
3487
  );
3338
3488
  }
@@ -3341,25 +3491,30 @@ export async function runAdapterConformance(
3341
3491
 
3342
3492
  await record('security.metadata-own-seat', async () => {
3343
3493
  const peer = await environment.admin.createDrone(principalA, cubeA, workerRoleA);
3344
- const peerBefore = await environment.admin.inspectDroneRuntimeState(peer);
3345
- const managedBefore = await environment.admin.inspectDroneRuntimeState(managedWorker);
3346
- const ownBefore = await environment.admin.inspectDroneRuntimeState(metadataDroneA);
3494
+ const rosterBefore = await environment.operations.listDrones(credentialA, cubeA);
3495
+ expectStatus(rosterBefore, 200, 'Pre-update metadata roster');
3496
+ const peerBefore = listedDrone(rosterBefore, peer.id);
3497
+ const managedBefore = listedDrone(rosterBefore, managedWorker.id);
3498
+ const ownBefore = listedDrone(rosterBefore, metadataDroneA.id);
3499
+ invariant(peerBefore && managedBefore && ownBefore, 'Pre-update metadata roster omitted a fixture drone.');
3347
3500
  const response = await environment.operations.selfMetadataUpdate(
3348
3501
  metadataSessionA,
3349
3502
  cubeA,
3350
3503
  createProtocolEnvelope('metadata-own-seat', { agent_kind: 'claude' }),
3351
3504
  );
3352
3505
  expectStatus(response, 200, 'Own-seat metadata update');
3506
+ const rosterAfter = await environment.operations.listDrones(credentialA, cubeA);
3507
+ expectStatus(rosterAfter, 200, 'Post-update metadata roster');
3353
3508
  invariant(
3354
- same(await environment.admin.inspectDroneRuntimeState(peer), peerBefore),
3509
+ same(listedDrone(rosterAfter, peer.id), peerBefore),
3355
3510
  'Own-seat update mutated a peer seat.',
3356
3511
  );
3357
3512
  invariant(
3358
- same(await environment.admin.inspectDroneRuntimeState(managedWorker), managedBefore),
3513
+ same(listedDrone(rosterAfter, managedWorker.id), managedBefore),
3359
3514
  'Own-seat update mutated another existing seat.',
3360
3515
  );
3361
3516
  invariant(
3362
- (await environment.admin.inspectDroneRuntimeState(metadataDroneA)).role_id === ownBefore.role_id,
3517
+ listedDrone(rosterAfter, metadataDroneA.id)?.role_id === ownBefore.role_id,
3363
3518
  'Metadata update changed the current seat role.',
3364
3519
  );
3365
3520
  expectError(
@@ -3401,7 +3556,12 @@ export async function runAdapterConformance(
3401
3556
  );
3402
3557
  rejectedStates.push(['evicted', evicted, evictedSession, 410, ErrorCode.DRONE_EVICTED]);
3403
3558
  for (const [label, drone, session, status, code] of rejectedStates) {
3404
- const before = await environment.admin.inspectDroneRuntimeState(drone);
3559
+ const rosterBefore = label === 'revoked'
3560
+ ? await environment.operations.listDrones(credentialA, cubeA)
3561
+ : null;
3562
+ if (rosterBefore) expectStatus(rosterBefore, 200, 'Pre-denial revoked metadata roster');
3563
+ const droneBefore = rosterBefore ? listedDrone(rosterBefore, drone.id) : null;
3564
+ if (rosterBefore) invariant(droneBefore, 'Pre-denial roster omitted the revoked metadata seat.');
3405
3565
  expectError(
3406
3566
  await environment.operations.selfMetadataUpdate(
3407
3567
  session,
@@ -3412,10 +3572,14 @@ export async function runAdapterConformance(
3412
3572
  code,
3413
3573
  `${label} metadata session`,
3414
3574
  );
3415
- invariant(
3416
- same(await environment.admin.inspectDroneRuntimeState(drone), before),
3417
- `${label} metadata denial mutated state.`,
3418
- );
3575
+ if (droneBefore) {
3576
+ const rosterAfter = await environment.operations.listDrones(credentialA, cubeA);
3577
+ expectStatus(rosterAfter, 200, 'Post-denial revoked metadata roster');
3578
+ invariant(
3579
+ same(listedDrone(rosterAfter, drone.id), droneBefore),
3580
+ 'Revoked metadata denial mutated the protocol-visible seat.',
3581
+ );
3582
+ }
3419
3583
  }
3420
3584
  return {
3421
3585
  own_seat_only: true,
@@ -3446,7 +3610,10 @@ export async function runAdapterConformance(
3446
3610
  );
3447
3611
  expectStatus(attachedB, 200, 'Cube B metadata attach');
3448
3612
  metadataDroneB = { id: decodeAttachResponseEnvelope(attachedB.body).payload.drone.id };
3449
- const beforeB = await environment.admin.inspectDroneRuntimeState(metadataDroneB);
3613
+ const rosterBefore = await environment.operations.listDrones(credentialB, cubeB);
3614
+ expectStatus(rosterBefore, 200, 'Pre-probe cube B roster');
3615
+ const beforeB = listedDrone(rosterBefore, metadataDroneB.id);
3616
+ invariant(beforeB, 'Pre-probe cube B roster omitted its metadata seat.');
3450
3617
  const foreign = await environment.operations.selfMetadataUpdate(
3451
3618
  metadataSessionA,
3452
3619
  cubeB,
@@ -3460,17 +3627,19 @@ export async function runAdapterConformance(
3460
3627
  );
3461
3628
  expectError(unknown, 404, ErrorCode.NOT_FOUND, 'Unknown-cube metadata update');
3462
3629
  invariant(same(foreign.body, unknown.body), 'Foreign and unknown metadata probes were distinguishable.');
3463
- invariant(
3464
- same(await environment.admin.inspectDroneRuntimeState(metadataDroneB), beforeB),
3465
- 'Cross-cube metadata update mutated the foreign seat.',
3466
- );
3630
+ const rosterAfter = await environment.operations.listDrones(credentialB, cubeB);
3631
+ expectStatus(rosterAfter, 200, 'Post-probe cube B roster');
3632
+ invariant(same(listedDrone(rosterAfter, metadataDroneB.id), beforeB), 'Cross-cube metadata update mutated the foreign seat.');
3467
3633
  const listedA = await environment.operations.listDrones(credentialA, cubeA);
3468
3634
  invariant(!listedDroneIds(listedA).includes(metadataDroneB.id), 'Cube A roster disclosed cube B metadata seat.');
3469
3635
  return { update_status: 404, foreign_unknown_indistinguishable: true, foreign_unchanged: true, roster_isolated: true };
3470
3636
  });
3471
3637
 
3472
3638
  await record('security.metadata-noninterference', async () => {
3473
- const before = await environment.admin.inspectDroneRuntimeState(metadataDroneA);
3639
+ const rosterBefore = await environment.operations.listDrones(credentialA, cubeA);
3640
+ expectStatus(rosterBefore, 200, 'Pre-update noninterference roster');
3641
+ const before = listedDrone(rosterBefore, metadataDroneA.id);
3642
+ invariant(before, 'Pre-update noninterference roster omitted the metadata seat.');
3474
3643
  for (const [requestId, patch] of [
3475
3644
  ['metadata-noninterference-known', { reported_model: 'openai/gpt-5.6-sol' }],
3476
3645
  ['metadata-noninterference-repeat', { reported_model: 'openai/gpt-5.6-sol' }],
@@ -3506,22 +3675,23 @@ export async function runAdapterConformance(
3506
3675
  }),
3507
3676
  );
3508
3677
  expectStatus(reattached, 200, 'Metadata non-interference reattach');
3509
- const after = await environment.admin.inspectDroneRuntimeState(metadataDroneA);
3510
- const { metadata: _beforeMetadata, metadata_revision: _beforeRevision, ...beforeInvariant } = before;
3511
- const { metadata: _afterMetadata, metadata_revision: _afterRevision, ...afterInvariant } = after;
3512
- invariant(same(beforeInvariant, afterInvariant), 'Metadata update changed authority/liveness/log state.');
3513
- return {
3514
- authority_unchanged: true,
3515
- role_unchanged: true,
3516
- liveness_unchanged: true,
3517
- logs_unchanged: true,
3518
- model_turns_unchanged: true,
3519
- };
3678
+ const rosterAfter = await environment.operations.listDrones(credentialA, cubeA);
3679
+ expectStatus(rosterAfter, 200, 'Post-update noninterference roster');
3680
+ const after = listedDrone(rosterAfter, metadataDroneA.id);
3681
+ invariant(after, 'Post-update noninterference roster omitted the metadata seat.');
3682
+ invariant(
3683
+ same(withoutRuntimeMetadata(before), withoutRuntimeMetadata(after)),
3684
+ 'Metadata update changed non-metadata roster state.',
3685
+ );
3686
+ return { non_metadata_roster_state_unchanged: true };
3520
3687
  });
3521
3688
 
3522
3689
  await record('security.metadata-secret-non-echo', async () => {
3523
3690
  const marker = 'SECRET-METADATA-MARKER';
3524
- const before = await environment.admin.inspectDroneRuntimeState(metadataDroneA);
3691
+ const rosterBefore = await environment.operations.listDrones(credentialA, cubeA);
3692
+ expectStatus(rosterBefore, 200, 'Pre-secret metadata roster');
3693
+ const before = listedDrone(rosterBefore, metadataDroneA.id);
3694
+ invariant(before, 'Pre-secret metadata roster omitted the metadata seat.');
3525
3695
  const response = await environment.operations.selfMetadataUpdate(
3526
3696
  metadataSessionA,
3527
3697
  cubeA,
@@ -3532,10 +3702,9 @@ export async function runAdapterConformance(
3532
3702
  );
3533
3703
  expectError(response, 400, ErrorCode.INVALID_INPUT, 'Secret-bearing metadata update');
3534
3704
  invariant(!JSON.stringify(response.body).includes(marker), 'Metadata error echoed hostile secret input.');
3535
- invariant(
3536
- same(await environment.admin.inspectDroneRuntimeState(metadataDroneA), before),
3537
- 'Secret-bearing metadata input was persisted.',
3538
- );
3705
+ const rosterAfter = await environment.operations.listDrones(credentialA, cubeA);
3706
+ expectStatus(rosterAfter, 200, 'Post-secret metadata roster');
3707
+ invariant(same(listedDrone(rosterAfter, metadataDroneA.id), before), 'Secret-bearing metadata input was persisted.');
3539
3708
  const hostileKeys = [
3540
3709
  'SECRET-METADATA-KEY-MARKER',
3541
3710
  `control\u001b[2J`,
@@ -3570,8 +3739,23 @@ export async function runAdapterConformance(
3570
3739
  });
3571
3740
 
3572
3741
  await record('security.active-stream-revocation', async () => {
3573
- invariant(liveCursor, 'Stream fixture did not produce a live cursor.');
3574
- const opened = await environment.operations.openStream(credentialA, cubeA, liveCursor);
3742
+ const principal = await environment.admin.createPrincipal('stream-revocation');
3743
+ const cube = await environment.admin.createCube('stream-revocation');
3744
+ await environment.admin.grantCube(principal, cube);
3745
+ const credential = await environment.admin.issueDroneSession(principal);
3746
+ const appended = await environment.operations.append(
3747
+ credential,
3748
+ cube,
3749
+ createProtocolEnvelope('stream-revocation-entry', {
3750
+ post_id: '00000000-0000-4000-8000-000000000315',
3751
+ to: 'broadcast',
3752
+ message: 'revocation cursor baseline',
3753
+ }),
3754
+ );
3755
+ expectStatus(appended, 201, 'Revocation fixture append');
3756
+ const entry = decodeAppendLogResultEnvelope(appended.body).payload.entry;
3757
+ const cursor = { id: entry.id, created_at: entry.created_at };
3758
+ const opened = await environment.operations.openStream(credential, cube, cursor);
3575
3759
  expectStatus(opened, 200, 'Revocation stream open');
3576
3760
  invariant(opened.stream, 'Successful revocation stream omitted its AsyncIterable.');
3577
3761
  const reader = new SseEventReader(opened.stream);
@@ -3580,7 +3764,7 @@ export async function runAdapterConformance(
3580
3764
  invariant(bookmark.type === 'bookmark' && bookmark.replay_complete, 'Fresh live stream did not complete replay.');
3581
3765
  const pending = reader.next();
3582
3766
  await provePending(pending, 'Idle live stream', pendingProbeMs);
3583
- await environment.admin.revokePrincipal(principalA);
3767
+ await environment.admin.revokePrincipal(principal);
3584
3768
  let terminated = false;
3585
3769
  try {
3586
3770
  await within(pending, 'Revoked stream termination', streamDeadlineMs);
@@ -3593,9 +3777,9 @@ export async function runAdapterConformance(
3593
3777
  await reader.close();
3594
3778
  }
3595
3779
  const rejected = await environment.operations.read(
3596
- credentialA,
3597
- cubeA,
3598
- createProtocolEnvelope('read-revoked', { cursor: liveCursor, limit: 10 }),
3780
+ credential,
3781
+ cube,
3782
+ createProtocolEnvelope('read-revoked', { cursor, limit: 10 }),
3599
3783
  );
3600
3784
  expectError(rejected, 401, ErrorCode.SESSION_REVOKED, 'Post-revocation request');
3601
3785
  return { stream_terminated: true, subsequent_status: 401, subsequent_code: ErrorCode.SESSION_REVOKED };
@@ -3627,15 +3811,16 @@ export async function runAdapterConformance(
3627
3811
  const writer = await enrollParent('delete-writer', 'W', '704');
3628
3812
  const outsider = await enrollParent('delete-outsider', 'O', '705');
3629
3813
  await environment.admin.grantCreateCubeCapability(creator.principal);
3814
+ const deleteCubeRequest = {
3815
+ retry_key: '00000000-0000-4000-8000-000000000706',
3816
+ name: 'Disposable Cube',
3817
+ working_repo_name: 'disposable-cube',
3818
+ repository: { kind: 'local' as const, value: '00000000-0000-4000-8000-000000000707' },
3819
+ template: 'software-dev' as const,
3820
+ };
3630
3821
  const createResponse = await environment.operations.createCube(
3631
3822
  creator.credential,
3632
- createProtocolEnvelope('delete-cube-create', {
3633
- retry_key: '00000000-0000-4000-8000-000000000706',
3634
- name: 'Disposable Cube',
3635
- working_repo_name: 'disposable-cube',
3636
- repository: { kind: 'local', value: '00000000-0000-4000-8000-000000000707' },
3637
- template: 'default',
3638
- }),
3823
+ createProtocolEnvelope('delete-cube-create', deleteCubeRequest),
3639
3824
  );
3640
3825
  expectStatus(createResponse, 201, 'Disposable cube creation');
3641
3826
  const created = decodeCreateCubeResponseEnvelope(createResponse.body).payload;
@@ -3646,6 +3831,17 @@ export async function runAdapterConformance(
3646
3831
  await environment.admin.grantCube(writer.principal, cube, 'write');
3647
3832
  const drone = await environment.admin.createDrone(creator.principal, cube, role);
3648
3833
  const droneCredential = await environment.admin.issueManagedDroneSession(drone);
3834
+ const roleProbeSession = 'T'.repeat(43);
3835
+ const initialRoleProbe = await environment.operations.attach(
3836
+ manager.credential,
3837
+ createProtocolEnvelope('delete-role-shape-baseline', {
3838
+ cube_id: cube.id,
3839
+ role_id: role.id,
3840
+ session_credential: roleProbeSession,
3841
+ }),
3842
+ );
3843
+ expectStatus(initialRoleProbe, 200, 'Deletion default-role shape baseline');
3844
+ const roleProbeDrone = decodeAttachResponseEnvelope(initialRoleProbe.body).payload.drone;
3649
3845
  const append = await environment.operations.append(
3650
3846
  creator.credential,
3651
3847
  cube,
@@ -3667,8 +3863,50 @@ export async function runAdapterConformance(
3667
3863
  cube,
3668
3864
  createProtocolEnvelope('delete-decision', { topic: 'cleanup', decision: 'delete' }),
3669
3865
  ), 201, 'Deletion fixture decision');
3866
+ const readDenialState = async (label: string): Promise<unknown> => {
3867
+ const decisions = await environment.operations.listDecisions(
3868
+ manager.credential,
3869
+ cube,
3870
+ createProtocolEnvelope(`delete-${label}-decision-readback`, {}),
3871
+ );
3872
+ expectStatus(decisions, 200, `${label} deletion decision readback`);
3873
+ const active = decodeDecisionsResultEnvelope(decisions.body).payload.decisions;
3874
+ const log = await environment.operations.read(
3875
+ manager.credential,
3876
+ cube,
3877
+ createProtocolEnvelope(`delete-${label}-log-readback`, { cursor: null, limit: 500 }),
3878
+ );
3879
+ expectStatus(log, 200, `${label} deletion log readback`);
3880
+ const logPayload = decodeReadLogResultEnvelope(log.body).payload;
3881
+ const roster = await environment.operations.listDrones(manager.credential, cube);
3882
+ expectStatus(roster, 200, `${label} deletion roster readback`);
3883
+ const roleReadback = await environment.operations.attach(
3884
+ manager.credential,
3885
+ createProtocolEnvelope(`delete-${label}-role-readback`, {
3886
+ cube_id: cube.id,
3887
+ role_id: role.id,
3888
+ prior_drone_id: roleProbeDrone.id,
3889
+ session_credential: roleProbeSession,
3890
+ }),
3891
+ );
3892
+ expectStatus(roleReadback, 200, `${label} deletion role readback`);
3893
+ const rolePayload = decodeAttachResponseEnvelope(roleReadback.body).payload.role;
3894
+ return {
3895
+ decisions: active,
3896
+ entries: logPayload.entries,
3897
+ claims: logPayload.claims,
3898
+ drone: listedDrone(roster, drone.id),
3899
+ role: rolePayload,
3900
+ };
3901
+ };
3902
+ const denialBaseline = await readDenialState('baseline');
3903
+ const assertDenialState = async (label: string): Promise<void> => {
3904
+ invariant(
3905
+ same(await readDenialState(label), denialBaseline),
3906
+ `${label} cube deletion denial mutated protocol-visible cube state.`,
3907
+ );
3908
+ };
3670
3909
 
3671
- const beforeDenied = await environment.admin.inspectCubeManagementState(cube);
3672
3910
  for (const [kind, credential] of [
3673
3911
  ['read', reader.credential],
3674
3912
  ['write', writer.credential],
@@ -3684,10 +3922,7 @@ export async function runAdapterConformance(
3684
3922
  ErrorCode.ACCESS_DENIED,
3685
3923
  `${kind} cube deletion`,
3686
3924
  );
3687
- invariant(
3688
- same(await environment.admin.inspectCubeManagementState(cube), beforeDenied),
3689
- `${kind} cube deletion denial mutated the cube.`,
3690
- );
3925
+ await assertDenialState(kind);
3691
3926
  }
3692
3927
  expectError(
3693
3928
  await environment.operations.deleteCube(
@@ -3699,6 +3934,7 @@ export async function runAdapterConformance(
3699
3934
  ErrorCode.NOT_FOUND,
3700
3935
  'Never-authorized cube deletion',
3701
3936
  );
3937
+ await assertDenialState('outsider');
3702
3938
 
3703
3939
  const parentStream = await environment.operations.openStream(manager.credential, cube, null);
3704
3940
  const droneStream = await environment.operations.openStream(droneCredential, cube, null);
@@ -3751,22 +3987,6 @@ export async function runAdapterConformance(
3751
3987
  await streamReader.close();
3752
3988
  }
3753
3989
 
3754
- invariant(
3755
- same(await environment.admin.inspectDeletedCube(cube), {
3756
- cube_exists: false,
3757
- role_count: 0,
3758
- drone_count: 0,
3759
- log_count: 0,
3760
- claim_count: 0,
3761
- decision_count: 0,
3762
- grant_count: 0,
3763
- cube_create_binding_count: 0,
3764
- repository_association_count: 0,
3765
- active_stream_count: 0,
3766
- terminal_credential_count: 5,
3767
- }),
3768
- 'Cube deletion did not atomically remove cube-owned state and preserve only terminal credentials.',
3769
- );
3770
3990
  for (const [kind, credential] of [
3771
3991
  ['creator', creator.credential],
3772
3992
  ['manager', manager.credential],
@@ -3815,66 +4035,28 @@ export async function runAdapterConformance(
3815
4035
  ErrorCode.NOT_FOUND,
3816
4036
  'Never-authorized post-delete request',
3817
4037
  );
3818
- await environment.admin.restartAuthority();
3819
- for (const [kind, credential] of [
3820
- ['creator', creator.credential],
3821
- ['manager', manager.credential],
3822
- ['reader', reader.credential],
3823
- ['writer', writer.credential],
3824
- ['drone', droneCredential],
3825
- ] as const) {
3826
- expectError(
3827
- await environment.operations.read(
3828
- credential,
3829
- cube,
3830
- createProtocolEnvelope(`delete-${kind}-after-restart`, { cursor: null, limit: 1 }),
3831
- ),
3832
- PROTOCOL_HTTP_CONTRACT.cube_deleted_status,
3833
- ErrorCode.CUBE_DELETED,
3834
- `${kind} post-restart deleted-cube request`,
3835
- );
3836
- expectError(
3837
- await environment.operations.deleteCube(
3838
- credential,
3839
- cube,
3840
- createProtocolEnvelope(`delete-${kind}-repeat-after-restart`, {}),
3841
- ),
3842
- PROTOCOL_HTTP_CONTRACT.cube_deleted_status,
3843
- ErrorCode.CUBE_DELETED,
3844
- `${kind} post-restart DELETE`,
3845
- );
3846
- }
3847
- expectError(
3848
- await environment.operations.deleteCube(
3849
- outsider.credential,
3850
- cube,
3851
- createProtocolEnvelope('delete-outsider-hidden-repeat-after-restart', {}),
3852
- ),
3853
- 404,
3854
- ErrorCode.NOT_FOUND,
3855
- 'Never-authorized post-restart DELETE',
4038
+ const recreatedResponse = await environment.operations.createCube(
4039
+ creator.credential,
4040
+ createProtocolEnvelope('delete-cube-recreate', deleteCubeRequest),
3856
4041
  );
3857
- expectError(
3858
- await environment.operations.read(
3859
- outsider.credential,
3860
- cube,
3861
- createProtocolEnvelope('delete-outsider-hidden-after-restart', { cursor: null, limit: 1 }),
3862
- ),
3863
- 404,
3864
- ErrorCode.NOT_FOUND,
3865
- 'Never-authorized post-restart request',
4042
+ expectStatus(recreatedResponse, 201, 'Post-delete cube recreation');
4043
+ const recreated = decodeCreateCubeResponseEnvelope(recreatedResponse.body).payload;
4044
+ invariant(
4045
+ recreated.result === 'created' && recreated.cube_id !== cube.id,
4046
+ 'Post-delete recreation resolved retained cube-owned creation state.',
3866
4047
  );
3867
4048
  return {
3868
4049
  deletion_status: 200,
3869
- cascade_complete: true,
3870
4050
  terminal_stream_error: ErrorCode.CUBE_DELETED,
3871
4051
  terminal_http_status: 410,
3872
- terminal_state_durable_after_restart: true,
3873
4052
  unknown_hidden_status: 404,
3874
4053
  non_member_manager: true,
4054
+ recreation_created_new_cube: true,
3875
4055
  };
3876
4056
  });
3877
4057
 
3878
- const normalizedTranscript = results.map(({ id, observations }) => ({ id, observations }));
4058
+ const normalizedTranscript = results
4059
+ .filter((result) => !result.skipped)
4060
+ .map(({ id, observations }) => ({ id, observations }));
3879
4061
  return { ok: results.every((result) => result.ok), results, normalizedTranscript };
3880
4062
  }