borgmcp-shared 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +29 -7
  2. package/dist/conformance/adapter.d.ts +54 -1
  3. package/dist/conformance/adapter.d.ts.map +1 -1
  4. package/dist/conformance/adapter.js +265 -1
  5. package/dist/conformance/adapter.js.map +1 -1
  6. package/dist/conformance/index.d.ts +9 -0
  7. package/dist/conformance/index.d.ts.map +1 -1
  8. package/dist/conformance/index.js +57 -1
  9. package/dist/conformance/index.js.map +1 -1
  10. package/dist/index.d.ts +1 -0
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +1 -0
  13. package/dist/index.js.map +1 -1
  14. package/dist/protocol/contract.d.ts +30 -2
  15. package/dist/protocol/contract.d.ts.map +1 -1
  16. package/dist/protocol/contract.js +62 -4
  17. package/dist/protocol/contract.js.map +1 -1
  18. package/dist/protocol/types.d.ts +16 -5
  19. package/dist/protocol/types.d.ts.map +1 -1
  20. package/dist/runtime-metadata.d.ts +28 -0
  21. package/dist/runtime-metadata.d.ts.map +1 -0
  22. package/dist/runtime-metadata.js +251 -0
  23. package/dist/runtime-metadata.js.map +1 -0
  24. package/dist/templates.d.ts +13 -13
  25. package/dist/templates.d.ts.map +1 -1
  26. package/dist/templates.js +342 -673
  27. package/dist/templates.js.map +1 -1
  28. package/docs/compatibility.md +29 -1
  29. package/docs/enrollment.md +13 -5
  30. package/docs/releasing.md +15 -4
  31. package/package.json +5 -1
  32. package/src/conformance/adapter.ts +457 -0
  33. package/src/conformance/index.ts +66 -1
  34. package/src/index.ts +1 -0
  35. package/src/protocol/contract.ts +110 -5
  36. package/src/protocol/types.ts +18 -5
  37. package/src/runtime-metadata.ts +304 -0
  38. package/src/templates.ts +365 -803
package/README.md CHANGED
@@ -34,6 +34,7 @@ import { TEMPLATES } from 'borgmcp-shared/templates';
34
34
  import { patchRoleSectionText } from 'borgmcp-shared/role-section';
35
35
  import { compareBroadcastHwm } from 'borgmcp-shared/log-stream-hwm';
36
36
  import { formatDroneAddressToken } from 'borgmcp-shared/drone-address';
37
+ import { canonicalizeRepositoryIdentity } from 'borgmcp-shared/runtime-metadata';
37
38
  import type { AppendLogRequest } from 'borgmcp-shared/protocol';
38
39
  import { ADAPTER_CONFORMANCE_FIXTURES } from 'borgmcp-shared/conformance';
39
40
  ```
@@ -50,6 +51,8 @@ The supported subpaths are:
50
51
  - `borgmcp-shared/role-section`: lossless role-text parsing and patching.
51
52
  - `borgmcp-shared/log-stream-hwm`: broadcast cursor ordering.
52
53
  - `borgmcp-shared/drone-address`: stable short drone-address rendering.
54
+ - `borgmcp-shared/runtime-metadata`: pure validation and canonical repository
55
+ identity helpers for advisory local seat metadata.
53
56
 
54
57
  Generated declaration files are included in every published package. Public
55
58
  functions and contracts include API documentation in their TypeScript sources.
@@ -94,6 +97,12 @@ versioned request and success envelopes. An evicted seat's former bearer receive
94
97
  the terminal `410 DRONE_EVICTED` signal; revoked sessions return
95
98
  `401 SESSION_REVOKED`, while expired sessions return the only recoverable
96
99
  authentication outcome, `401 AUTH_EXPIRED`.
100
+ An authenticated drone session updates only its own advisory identity with
101
+ `PATCH /api/cubes/:cubeId/drones/self/metadata`. The strict patch carries no
102
+ target seat ID. Metadata never grants authority or changes role, wake, liveness,
103
+ timestamp, log, routing, or model-execution state.
104
+ Identity responses include `runtime_metadata_reported`, keeping an omitted
105
+ attach report distinct from a reported all-null or explicitly cleared state.
97
106
  See [docs/enrollment.md](docs/enrollment.md) for purpose-bound owner enrollment,
98
107
  ordinary ungranted enrollment, cube creation, pending enrollment, and retry contracts.
99
108
 
@@ -107,6 +116,9 @@ credential misuse, isolation and revocation, SSE framing/replay/cursor ordering,
107
116
  executable enrollment authority/retry/mismatch/redaction and cube-create
108
117
  idempotency, acks, claims, decisions, cube-scoped drone reassignment, role-class
109
118
  and single-seat invariants, eviction exclusion, and terminal bearer signaling.
119
+ The same runner covers complete attach reports, own-seat metadata self-healing,
120
+ canonical repository identity, invalid-patch atomicity, cross-cube isolation,
121
+ secret non-echo, and authority/liveness/log non-interference.
110
122
  Manage-scoped cube, role, taxonomy, decision, and drone operations also share an
111
123
  authority matrix: managing parents may mutate; known same-cube read/write
112
124
  parents receive `403 ACCESS_DENIED`; drone sessions remain non-managing; and
@@ -120,8 +132,8 @@ its local/self-hosted implementation. The package does not define a second
120
132
  authority, migration target, or fallback implementation.
121
133
 
122
134
  The package's own suite covers built-in templates, role-section patching,
123
- broadcast high-water-mark ordering, drone-address formatting, and current public
124
- response shapes.
135
+ broadcast high-water-mark ordering, drone-address formatting, runtime metadata
136
+ canonicalization, and current public response shapes.
125
137
 
126
138
  ## Compatibility
127
139
 
@@ -142,11 +154,21 @@ immutable, but its artifact predates the local/self-hosted package cleanup. The
142
154
  immutable `v0.4.1` verification artifact exposed a platform-dependent SBOM audit
143
155
  and must never be published, moved, reused, rerun, or substituted.
144
156
  `borgmcp-shared@0.4.2` is published and immutable. `borgmcp-shared@0.4.3` is the
145
- immutable protocol v2 session-lifecycle release. This source now identifies the
146
- unpublished `0.5.0` protocol v3 attach-session contract release: attach responses
147
- carry the exact non-expiring `session: { id }` shape. This reviewed version bump
148
- grants no tag or publish authority; creating the annotated `v0.5.0` tag and
149
- publishing its exact reviewed artifact remain separate, independently gated steps.
157
+ immutable protocol v2 session-lifecycle release. `borgmcp-shared@0.5.0` is the published protocol v3 attach-session contract
158
+ release: attach responses carry the exact non-expiring `session: { id }` shape.
159
+ `borgmcp-shared@0.5.1` is published and immutable under the accepted attempt-1
160
+ registry-propagation incident: annotated tag object `045268aa8873da330819860012ecaddb4bc2883c` peels to
161
+ `1981d7373e77f6edb4567872c1544bdbe2b1ef20`; workflow run `29984423571` published exact integrity
162
+ `sha512-XUJq+FjY/cbarU9V1dIWnhNYcqyURTiGb6KyIzg99gy5hk/fEs5ee/8X/qvp7pw1Rshqt2J6I3TVbwJdlde2tA==` and must never be rerun. Independent npm verification
163
+ confirmed its registry signature and SLSA provenance. `borgmcp-shared@0.6.0` was
164
+ never published: annotated tag object `90a1cf686a0ce32a7aef836b0b82a930191b9030`
165
+ peels to protected-main commit `fd69b08586481a60c88099dede8e4e066f73f2f2`;
166
+ attempt-1 workflow run `30054936226` failed in tests before build, packaging,
167
+ authentication, or registry mutation and must never be rerun or moved.
168
+ This source now identifies the unpublished `0.6.1` runtime-metadata contract release. This
169
+ reviewed version bump grants no tag or publish authority; creating annotated
170
+ `v0.6.1` and publishing
171
+ its exact reviewed artifact remain separate, independently gated steps.
150
172
  Consumers update shared, server, and client together: peers carrying protocol v2
151
173
  and v3 reject each other during credential-free preflight. No registry token
152
174
  belongs in this repository, package metadata, lockfiles, or a committed `.npmrc`;
@@ -1,4 +1,4 @@
1
- import { type CreateCubeResponse, type LogCursor } from '../protocol/index.js';
1
+ import { type CreateCubeResponse, type LogCursor, type DroneRuntimeMetadata } from '../protocol/index.js';
2
2
  export interface ConformanceHttpResponse {
3
3
  status: number;
4
4
  body: unknown;
@@ -15,6 +15,35 @@ export interface ConformanceRole {
15
15
  export interface ConformanceDrone {
16
16
  readonly id: string;
17
17
  }
18
+ export interface ConformanceDroneRuntimeState {
19
+ readonly metadata: DroneRuntimeMetadata;
20
+ readonly metadata_reported: boolean;
21
+ readonly metadata_revision: number;
22
+ readonly cube_id: string;
23
+ readonly role_id: string;
24
+ readonly session_state: 'active' | 'revoked' | 'expired';
25
+ readonly evicted: boolean;
26
+ readonly last_seen: string;
27
+ readonly heartbeat_count: number;
28
+ readonly wake_count: number;
29
+ readonly log_count: number;
30
+ readonly model_turn_count: number;
31
+ readonly grant_access: ConformanceCubeAccess | null;
32
+ readonly server_capabilities: readonly string[];
33
+ readonly principal_revoked: boolean;
34
+ readonly session_bound: boolean;
35
+ readonly last_log_post: string | null;
36
+ readonly last_regen_at: string | null;
37
+ readonly last_read_log_at: string | null;
38
+ readonly last_event_received_at: string | null;
39
+ readonly wake_path: 'live';
40
+ readonly wake_alert: null;
41
+ readonly monitor_armed: boolean;
42
+ readonly sse_connected: boolean;
43
+ readonly claim_count: number;
44
+ readonly decision_count: number;
45
+ readonly routing_eligible: boolean;
46
+ }
18
47
  export type ConformanceCubeAccess = 'read' | 'write' | 'manage';
19
48
  export interface ConformanceCubeManagementState {
20
49
  readonly directive: string;
@@ -75,6 +104,7 @@ export interface ConformanceAdmin {
75
104
  readonly evicted: boolean;
76
105
  readonly session_revoked: boolean;
77
106
  }>;
107
+ inspectDroneRuntimeState(drone: ConformanceDrone): Promise<ConformanceDroneRuntimeState>;
78
108
  inspectCubeManagementState(cube: ConformanceCube): Promise<ConformanceCubeManagementState>;
79
109
  grantCreateCubeCapability(principal: ConformancePrincipal): Promise<void>;
80
110
  issueDroneSession(principal: ConformancePrincipal): Promise<string>;
@@ -91,6 +121,8 @@ export interface ConformanceOperations {
91
121
  protocol(credential: string | null): Promise<ConformanceHttpResponse>;
92
122
  enroll(request: unknown): Promise<ConformanceHttpResponse>;
93
123
  createCube(credential: string | null, request: unknown): Promise<ConformanceHttpResponse>;
124
+ attach(credential: string, request: unknown): Promise<ConformanceHttpResponse>;
125
+ selfMetadataUpdate(credential: string, cube: ConformanceCube, request: unknown): Promise<ConformanceHttpResponse>;
94
126
  append(credential: string, cube: ConformanceCube, request: unknown): Promise<ConformanceHttpResponse>;
95
127
  appendRaw(credential: string, cube: ConformanceCube, body: string): Promise<ConformanceHttpResponse>;
96
128
  read(credential: string, cube: ConformanceCube, request: unknown): Promise<ConformanceHttpResponse>;
@@ -163,6 +195,27 @@ export declare const ADAPTER_CONFORMANCE_FIXTURES: readonly [{
163
195
  }, {
164
196
  readonly id: "security.drone-session-rejection-causes";
165
197
  readonly area: "security";
198
+ }, {
199
+ readonly id: "metadata.attach-report";
200
+ readonly area: "metadata";
201
+ }, {
202
+ readonly id: "metadata.self-heal-patch";
203
+ readonly area: "metadata";
204
+ }, {
205
+ readonly id: "security.metadata-invalid-atomic";
206
+ readonly area: "security";
207
+ }, {
208
+ readonly id: "security.metadata-own-seat";
209
+ readonly area: "security";
210
+ }, {
211
+ readonly id: "security.metadata-cross-cube-isolation";
212
+ readonly area: "security";
213
+ }, {
214
+ readonly id: "security.metadata-noninterference";
215
+ readonly area: "security";
216
+ }, {
217
+ readonly id: "security.metadata-secret-non-echo";
218
+ readonly area: "security";
166
219
  }, {
167
220
  readonly id: "security.active-stream-revocation";
168
221
  readonly area: "security";
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/conformance/adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/conformance/adapter.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { ErrorCode, compareLogCursor, createProtocolEnvelope, decodeCreateCubeResponseEnvelope, decodeAppendLogResultEnvelope, decodeDecisionResultEnvelope, decodeDecisionsResultEnvelope, decodeEnrollmentExchangeResponseEnvelope, decodeEvictDroneResultEnvelope, decodeProtocolEnvelope, decodeProtocolErrorEnvelope, decodeProtocolTagPreflight, decodeReadLogResultEnvelope, decodeReassignDroneResultEnvelope, decodeSseFrames, PROTOCOL_LIMIT_CEILINGS, PROTOCOL_HTTP_CONTRACT, PROTOCOL_VERSION, utf8ByteLength, } from '../protocol/index.js';
1
+ import { ErrorCode, compareLogCursor, createProtocolEnvelope, decodeCreateCubeResponseEnvelope, decodeAppendLogResultEnvelope, decodeDecisionResultEnvelope, decodeDecisionsResultEnvelope, decodeEnrollmentExchangeResponseEnvelope, decodeAttachResponseEnvelope, decodeDroneRuntimeMetadataPatch, decodeEvictDroneResultEnvelope, decodeProtocolEnvelope, decodeProtocolErrorEnvelope, decodeProtocolTagPreflight, decodeReadLogResultEnvelope, decodeReassignDroneResultEnvelope, decodeUpdateDroneRuntimeMetadataResponseEnvelope, decodeSseFrames, PROTOCOL_LIMIT_CEILINGS, PROTOCOL_HTTP_CONTRACT, PROTOCOL_VERSION, utf8ByteLength, } from '../protocol/index.js';
2
2
  import { ENROLLMENT_RETRY_CONFORMANCE } from './index.js';
3
3
  export const ADAPTER_CONFORMANCE_FIXTURES = [
4
4
  { id: 'http.unauthenticated-liveness', area: 'http' },
@@ -19,6 +19,13 @@ export const ADAPTER_CONFORMANCE_FIXTURES = [
19
19
  { id: 'security.cross-cube-drone-management', area: 'security' },
20
20
  { id: 'drones.evict-terminal-signal', area: 'drones' },
21
21
  { id: 'security.drone-session-rejection-causes', area: 'security' },
22
+ { id: 'metadata.attach-report', area: 'metadata' },
23
+ { id: 'metadata.self-heal-patch', area: 'metadata' },
24
+ { id: 'security.metadata-invalid-atomic', area: 'security' },
25
+ { id: 'security.metadata-own-seat', area: 'security' },
26
+ { id: 'security.metadata-cross-cube-isolation', area: 'security' },
27
+ { id: 'security.metadata-noninterference', area: 'security' },
28
+ { id: 'security.metadata-secret-non-echo', area: 'security' },
22
29
  { id: 'security.active-stream-revocation', area: 'security' },
23
30
  ];
24
31
  const DEFAULT_STREAM_DEADLINE_MS = 5_000;
@@ -554,6 +561,9 @@ export async function runAdapterConformance(environment, options = {}) {
554
561
  let readCredential = '';
555
562
  let writeCredential = '';
556
563
  let workerSession = '';
564
+ let metadataDroneA;
565
+ let metadataDroneB;
566
+ let metadataSessionA = '';
557
567
  await record('security.drone-management-authorization', async () => {
558
568
  workerRoleA = await environment.admin.createRole(cubeA, {
559
569
  roleClass: 'worker', isHumanSeat: false,
@@ -788,6 +798,260 @@ export async function runAdapterConformance(environment, options = {}) {
788
798
  expired_code: ErrorCode.AUTH_EXPIRED,
789
799
  };
790
800
  });
801
+ const knownMetadata = {
802
+ agent_kind: 'opencode',
803
+ reported_model: 'openai/gpt-5.6-sol',
804
+ working_repo_name: 'Byte-Ventures/borg-mcp',
805
+ working_repo_origin: 'https://github.com/Byte-Ventures/borg-mcp',
806
+ };
807
+ await record('metadata.attach-report', async () => {
808
+ metadataSessionA = 'M'.repeat(43);
809
+ const created = await environment.operations.attach(credentialA, createProtocolEnvelope('metadata-attach-created', {
810
+ cube_id: cubeA.id,
811
+ role_id: workerRoleA.id,
812
+ session_credential: metadataSessionA,
813
+ runtime_metadata: {
814
+ ...knownMetadata,
815
+ working_repo_origin: 'git@github.com:Byte-Ventures/borg-mcp.git',
816
+ },
817
+ }));
818
+ expectStatus(created, 200, 'Metadata attach create');
819
+ const createdPayload = decodeAttachResponseEnvelope(created.body).payload;
820
+ invariant(createdPayload.result === 'created', 'First metadata attach did not create a seat.');
821
+ invariant(same(createdPayload.drone.runtime_metadata, knownMetadata), 'Attach did not echo canonical metadata.');
822
+ invariant(createdPayload.drone.runtime_metadata_reported, 'Present attach report was not marked reported.');
823
+ metadataDroneA = { id: createdPayload.drone.id };
824
+ const unavailableSession = 'N'.repeat(43);
825
+ const unavailable = await environment.operations.attach(credentialA, createProtocolEnvelope('metadata-attach-unavailable', {
826
+ cube_id: cubeA.id,
827
+ role_id: workerRoleA.id,
828
+ session_credential: unavailableSession,
829
+ }));
830
+ expectStatus(unavailable, 200, 'Unavailable metadata attach');
831
+ const unavailableDrone = decodeAttachResponseEnvelope(unavailable.body).payload.drone;
832
+ invariant(same(unavailableDrone.runtime_metadata, {
833
+ agent_kind: null,
834
+ reported_model: null,
835
+ working_repo_name: null,
836
+ working_repo_origin: null,
837
+ }), 'Omitted attach report synthesized metadata.');
838
+ invariant(!unavailableDrone.runtime_metadata_reported, 'Omitted attach report was marked reported.');
839
+ const explicitUnknown = await environment.operations.attach(credentialA, createProtocolEnvelope('metadata-attach-explicit-unknown', {
840
+ cube_id: cubeA.id,
841
+ role_id: workerRoleA.id,
842
+ session_credential: 'U'.repeat(43),
843
+ runtime_metadata: {
844
+ agent_kind: null,
845
+ reported_model: null,
846
+ working_repo_name: null,
847
+ working_repo_origin: null,
848
+ },
849
+ }));
850
+ expectStatus(explicitUnknown, 200, 'Explicit unknown metadata attach');
851
+ const explicitUnknownDrone = decodeAttachResponseEnvelope(explicitUnknown.body).payload.drone;
852
+ invariant(explicitUnknownDrone.runtime_metadata_reported, 'All-null attach report was not marked reported.');
853
+ const reused = await environment.operations.attach(credentialA, createProtocolEnvelope('metadata-attach-reused', {
854
+ cube_id: cubeA.id,
855
+ role_id: workerRoleA.id,
856
+ prior_drone_id: metadataDroneA.id,
857
+ session_credential: metadataSessionA,
858
+ runtime_metadata: knownMetadata,
859
+ }));
860
+ expectStatus(reused, 200, 'Metadata attach reuse');
861
+ invariant(decodeAttachResponseEnvelope(reused.body).payload.result === 'reused', 'Prior seat was not reused.');
862
+ const cleared = await environment.operations.selfMetadataUpdate(metadataSessionA, cubeA, createProtocolEnvelope('metadata-clear-all', {
863
+ agent_kind: null,
864
+ reported_model: null,
865
+ working_repo_name: null,
866
+ working_repo_origin: null,
867
+ }));
868
+ expectStatus(cleared, 200, 'Clear-all metadata patch');
869
+ const clearedPayload = decodeUpdateDroneRuntimeMetadataResponseEnvelope(cleared.body).payload;
870
+ invariant(clearedPayload.runtime_metadata_reported, 'Clear-all patch lost reported state.');
871
+ invariant(same(clearedPayload.runtime_metadata, explicitUnknownDrone.runtime_metadata), 'Clear-all patch did not produce explicit unknown metadata.');
872
+ expectStatus(await environment.operations.selfMetadataUpdate(metadataSessionA, cubeA, createProtocolEnvelope('metadata-restore-known', knownMetadata)), 200, 'Restore known metadata');
873
+ return {
874
+ created: true,
875
+ reused: true,
876
+ report_states: [
877
+ unavailableDrone.runtime_metadata_reported,
878
+ explicitUnknownDrone.runtime_metadata_reported,
879
+ clearedPayload.runtime_metadata_reported,
880
+ ],
881
+ canonical_response: true,
882
+ };
883
+ });
884
+ await record('metadata.self-heal-patch', async () => {
885
+ const updates = [
886
+ { request_id: 'metadata-known-new', patch: { reported_model: 'openai/gpt-5.6-terra' } },
887
+ { request_id: 'metadata-null-clear', patch: { reported_model: null } },
888
+ { request_id: 'metadata-null-repeat', patch: { reported_model: null } },
889
+ { request_id: 'metadata-same-value', patch: { agent_kind: 'opencode' } },
890
+ ];
891
+ for (const update of updates) {
892
+ const response = await environment.operations.selfMetadataUpdate(metadataSessionA, cubeA, createProtocolEnvelope(update.request_id, update.patch));
893
+ expectStatus(response, 200, update.request_id);
894
+ decodeUpdateDroneRuntimeMetadataResponseEnvelope(response.body);
895
+ }
896
+ const state = await environment.admin.inspectDroneRuntimeState(metadataDroneA);
897
+ invariant(state.metadata.reported_model === null, 'Explicit null did not clear model metadata.');
898
+ invariant(state.metadata.agent_kind === 'opencode', 'Omitted field was not preserved.');
899
+ return { known_replace: true, omitted_unchanged: true, null_clear: true, repeat_safe: true };
900
+ });
901
+ await record('security.metadata-invalid-atomic', async () => {
902
+ const invalidPatches = [
903
+ {},
904
+ { agent_kind: 'OpenCode' },
905
+ { reported_model: '' },
906
+ { reported_model: 'a'.repeat(161) },
907
+ { reported_model: 'safe\u001b[2J' },
908
+ { reported_model: 'safe\u061cnext' },
909
+ { working_repo_name: 'owner/repo' },
910
+ { working_repo_name: 'owner/repo', working_repo_origin: 'https://user:secret@github.com/owner/repo' },
911
+ {
912
+ working_repo_name: 'owner/repo',
913
+ working_repo_origin: ['file:/', '', 'Users', 'secret', 'repo'].join('/'),
914
+ },
915
+ { role_id: workerRoleA.id },
916
+ { last_seen: '2026-07-14T10:00:00.000Z' },
917
+ ];
918
+ for (const [index, patch] of invalidPatches.entries()) {
919
+ const before = await environment.admin.inspectDroneRuntimeState(metadataDroneA);
920
+ const response = await environment.operations.selfMetadataUpdate(metadataSessionA, cubeA, createProtocolEnvelope(`metadata-invalid-${index}`, patch));
921
+ expectError(response, 400, ErrorCode.INVALID_INPUT, `Invalid metadata patch ${index}`);
922
+ invariant(same(await environment.admin.inspectDroneRuntimeState(metadataDroneA), before), `Invalid metadata patch ${index} partially mutated state.`);
923
+ }
924
+ return { cases: invalidPatches.length, atomic: true, prior_safe_state_retained: true };
925
+ });
926
+ await record('security.metadata-own-seat', async () => {
927
+ const peer = await environment.admin.createDrone(principalA, cubeA, workerRoleA);
928
+ const peerBefore = await environment.admin.inspectDroneRuntimeState(peer);
929
+ const managedBefore = await environment.admin.inspectDroneRuntimeState(managedWorker);
930
+ const ownBefore = await environment.admin.inspectDroneRuntimeState(metadataDroneA);
931
+ const response = await environment.operations.selfMetadataUpdate(metadataSessionA, cubeA, createProtocolEnvelope('metadata-own-seat', { agent_kind: 'claude' }));
932
+ expectStatus(response, 200, 'Own-seat metadata update');
933
+ invariant(same(await environment.admin.inspectDroneRuntimeState(peer), peerBefore), 'Own-seat update mutated a peer seat.');
934
+ invariant(same(await environment.admin.inspectDroneRuntimeState(managedWorker), managedBefore), 'Own-seat update mutated another existing seat.');
935
+ invariant((await environment.admin.inspectDroneRuntimeState(metadataDroneA)).role_id === ownBefore.role_id, 'Metadata update changed the current seat role.');
936
+ expectError(await environment.operations.selfMetadataUpdate(credentialA, cubeA, createProtocolEnvelope('metadata-manager-denied', { agent_kind: 'codex' })), 403, ErrorCode.ACCESS_DENIED, 'Manager metadata update');
937
+ expectError(await environment.operations.selfMetadataUpdate('Z'.repeat(43), cubeA, createProtocolEnvelope('metadata-invalid-session', { agent_kind: null })), 401, ErrorCode.AUTH_INVALID, 'Unknown metadata session');
938
+ const rejectedStates = [];
939
+ const revoked = await environment.admin.createDrone(principalA, cubeA, workerRoleA);
940
+ const revokedSession = await environment.admin.issueManagedDroneSession(revoked);
941
+ await environment.admin.revokeManagedDroneSession(revoked);
942
+ rejectedStates.push(['revoked', revoked, revokedSession, 401, ErrorCode.SESSION_REVOKED]);
943
+ const expired = await environment.admin.createDrone(principalA, cubeA, workerRoleA);
944
+ const expiredSession = await environment.admin.issueManagedDroneSession(expired);
945
+ await environment.admin.expireManagedDroneSession(expired);
946
+ rejectedStates.push(['expired', expired, expiredSession, 401, ErrorCode.AUTH_EXPIRED]);
947
+ const evicted = await environment.admin.createDrone(principalA, cubeA, workerRoleA);
948
+ const evictedSession = await environment.admin.issueManagedDroneSession(evicted);
949
+ expectStatus(await environment.operations.evictDrone(credentialA, cubeA, evicted, createProtocolEnvelope('metadata-evict-seat', {})), 200, 'Metadata seat eviction');
950
+ rejectedStates.push(['evicted', evicted, evictedSession, 410, ErrorCode.DRONE_EVICTED]);
951
+ for (const [label, drone, session, status, code] of rejectedStates) {
952
+ const before = await environment.admin.inspectDroneRuntimeState(drone);
953
+ expectError(await environment.operations.selfMetadataUpdate(session, cubeA, createProtocolEnvelope(`metadata-${label}-denied`, { agent_kind: null })), status, code, `${label} metadata session`);
954
+ invariant(same(await environment.admin.inspectDroneRuntimeState(drone), before), `${label} metadata denial mutated state.`);
955
+ }
956
+ return {
957
+ own_seat_only: true,
958
+ manager_denied: true,
959
+ unknown_session_denied: true,
960
+ revoked_expired_evicted_denied: true,
961
+ };
962
+ });
963
+ await record('security.metadata-cross-cube-isolation', async () => {
964
+ const sessionB = 'P'.repeat(43);
965
+ const metadataRoleB = await environment.admin.createRole(cubeB, {
966
+ roleClass: 'worker', isHumanSeat: false,
967
+ });
968
+ const attachedB = await environment.operations.attach(credentialB, createProtocolEnvelope('metadata-attach-b', {
969
+ cube_id: cubeB.id,
970
+ role_id: metadataRoleB.id,
971
+ session_credential: sessionB,
972
+ runtime_metadata: {
973
+ agent_kind: 'codex',
974
+ reported_model: null,
975
+ working_repo_name: 'Byte-Ventures/borg-mcp-server',
976
+ working_repo_origin: 'https://github.com/Byte-Ventures/borg-mcp-server',
977
+ },
978
+ }));
979
+ expectStatus(attachedB, 200, 'Cube B metadata attach');
980
+ metadataDroneB = { id: decodeAttachResponseEnvelope(attachedB.body).payload.drone.id };
981
+ const beforeB = await environment.admin.inspectDroneRuntimeState(metadataDroneB);
982
+ const foreign = await environment.operations.selfMetadataUpdate(metadataSessionA, cubeB, createProtocolEnvelope('metadata-cross-cube', { reported_model: 'foreign/probe' }));
983
+ expectError(foreign, 404, ErrorCode.NOT_FOUND, 'Cross-cube metadata update');
984
+ const unknown = await environment.operations.selfMetadataUpdate(metadataSessionA, { id: '90000000-0000-4000-8000-000000000001' }, createProtocolEnvelope('metadata-unknown-cube', { reported_model: 'foreign/probe' }));
985
+ expectError(unknown, 404, ErrorCode.NOT_FOUND, 'Unknown-cube metadata update');
986
+ invariant(same(foreign.body, unknown.body), 'Foreign and unknown metadata probes were distinguishable.');
987
+ invariant(same(await environment.admin.inspectDroneRuntimeState(metadataDroneB), beforeB), 'Cross-cube metadata update mutated the foreign seat.');
988
+ const listedA = await environment.operations.listDrones(credentialA, cubeA);
989
+ invariant(!listedDroneIds(listedA).includes(metadataDroneB.id), 'Cube A roster disclosed cube B metadata seat.');
990
+ return { update_status: 404, foreign_unknown_indistinguishable: true, foreign_unchanged: true, roster_isolated: true };
991
+ });
992
+ await record('security.metadata-noninterference', async () => {
993
+ const before = await environment.admin.inspectDroneRuntimeState(metadataDroneA);
994
+ for (const [requestId, patch] of [
995
+ ['metadata-noninterference-known', { reported_model: 'openai/gpt-5.6-sol' }],
996
+ ['metadata-noninterference-repeat', { reported_model: 'openai/gpt-5.6-sol' }],
997
+ ['metadata-noninterference-null', { reported_model: null }],
998
+ ]) {
999
+ expectStatus(await environment.operations.selfMetadataUpdate(metadataSessionA, cubeA, createProtocolEnvelope(requestId, patch)), 200, requestId);
1000
+ }
1001
+ expectError(await environment.operations.selfMetadataUpdate(metadataSessionA, cubeA, createProtocolEnvelope('metadata-noninterference-reject', { authority: 'manage' })), 400, ErrorCode.INVALID_INPUT, 'Rejected metadata non-interference update');
1002
+ const reattached = await environment.operations.attach(credentialA, createProtocolEnvelope('metadata-noninterference-reattach', {
1003
+ cube_id: cubeA.id,
1004
+ role_id: workerRoleA.id,
1005
+ prior_drone_id: metadataDroneA.id,
1006
+ session_credential: metadataSessionA,
1007
+ }));
1008
+ expectStatus(reattached, 200, 'Metadata non-interference reattach');
1009
+ const after = await environment.admin.inspectDroneRuntimeState(metadataDroneA);
1010
+ const { metadata: _beforeMetadata, metadata_revision: _beforeRevision, ...beforeInvariant } = before;
1011
+ const { metadata: _afterMetadata, metadata_revision: _afterRevision, ...afterInvariant } = after;
1012
+ invariant(same(beforeInvariant, afterInvariant), 'Metadata update changed authority/liveness/log state.');
1013
+ return {
1014
+ authority_unchanged: true,
1015
+ role_unchanged: true,
1016
+ liveness_unchanged: true,
1017
+ logs_unchanged: true,
1018
+ model_turns_unchanged: true,
1019
+ };
1020
+ });
1021
+ await record('security.metadata-secret-non-echo', async () => {
1022
+ const marker = 'SECRET-METADATA-MARKER';
1023
+ const before = await environment.admin.inspectDroneRuntimeState(metadataDroneA);
1024
+ const response = await environment.operations.selfMetadataUpdate(metadataSessionA, cubeA, createProtocolEnvelope('metadata-secret', {
1025
+ working_repo_name: 'owner/repo',
1026
+ working_repo_origin: `https://user:${marker}@github.com/owner/repo?token=${marker}`,
1027
+ }));
1028
+ expectError(response, 400, ErrorCode.INVALID_INPUT, 'Secret-bearing metadata update');
1029
+ invariant(!JSON.stringify(response.body).includes(marker), 'Metadata error echoed hostile secret input.');
1030
+ invariant(same(await environment.admin.inspectDroneRuntimeState(metadataDroneA), before), 'Secret-bearing metadata input was persisted.');
1031
+ const hostileKeys = [
1032
+ 'SECRET-METADATA-KEY-MARKER',
1033
+ `control\u001b[2J`,
1034
+ `bidi\u061cmarker`,
1035
+ `token_${'a'.repeat(48)}`,
1036
+ ];
1037
+ for (const [index, key] of hostileKeys.entries()) {
1038
+ const rejected = await environment.operations.selfMetadataUpdate(metadataSessionA, cubeA, createProtocolEnvelope(`metadata-secret-key-${index}`, { [key]: 'x' }));
1039
+ expectError(rejected, 400, ErrorCode.INVALID_INPUT, `Hostile metadata key ${index}`);
1040
+ invariant(!JSON.stringify(rejected.body).includes(key), `Metadata error echoed hostile key ${index}.`);
1041
+ }
1042
+ const logs = await environment.operations.read(credentialA, cubeA, createProtocolEnvelope('metadata-secret-log-read', { cursor: null, limit: 500 }));
1043
+ expectStatus(logs, 200, 'Metadata secret log read');
1044
+ for (const hostile of [marker, ...hostileKeys]) {
1045
+ invariant(!JSON.stringify(logs.body).includes(hostile), 'Metadata input leaked into activity logs.');
1046
+ }
1047
+ return {
1048
+ rejected_pre_persistence: true,
1049
+ response_secret_free: true,
1050
+ state_secret_free: true,
1051
+ log_secret_free: true,
1052
+ unknown_key_secret_free: true,
1053
+ };
1054
+ });
791
1055
  await record('security.active-stream-revocation', async () => {
792
1056
  invariant(liveCursor, 'Stream fixture did not produce a live cursor.');
793
1057
  const opened = await environment.operations.openStream(credentialA, cubeA, liveCursor);