borgmcp-shared 0.11.0 → 0.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -1
- package/RELEASES.md +14 -0
- package/dist/conformance/adapter.d.ts +4 -0
- package/dist/conformance/adapter.d.ts.map +1 -1
- package/dist/conformance/adapter.js +109 -10
- package/dist/conformance/adapter.js.map +1 -1
- package/dist/conformance/index.d.ts +13 -0
- package/dist/conformance/index.d.ts.map +1 -1
- package/dist/conformance/index.js +84 -14
- package/dist/conformance/index.js.map +1 -1
- package/dist/protocol/contract.d.ts +2 -1
- package/dist/protocol/contract.d.ts.map +1 -1
- package/dist/protocol/contract.js +9 -4
- package/dist/protocol/contract.js.map +1 -1
- package/dist/protocol/coordination.d.ts.map +1 -1
- package/dist/protocol/coordination.js +8 -2
- package/dist/protocol/coordination.js.map +1 -1
- package/dist/protocol/errors.d.ts +1 -0
- package/dist/protocol/errors.d.ts.map +1 -1
- package/dist/protocol/errors.js +1 -0
- package/dist/protocol/errors.js.map +1 -1
- package/dist/protocol/types.d.ts +2 -0
- package/dist/protocol/types.d.ts.map +1 -1
- package/dist/protocol/version.d.ts +1 -1
- package/dist/protocol/version.js +1 -1
- package/docs/release-records.json +117 -0
- package/docs/releases/0.12.0.md +7 -0
- package/docs/releases/0.12.1.md +7 -0
- package/docs/releases/0.12.2.md +7 -0
- package/docs/releasing.md +62 -75
- package/package.json +2 -1
- package/src/conformance/adapter.ts +137 -9
- package/src/conformance/index.ts +102 -15
- package/src/protocol/contract.ts +11 -5
- package/src/protocol/coordination.ts +8 -2
- package/src/protocol/errors.ts +1 -0
- package/src/protocol/types.ts +2 -0
- package/src/protocol/version.ts +2 -2
package/README.md
CHANGED
|
@@ -104,7 +104,13 @@ Versioned JSON coordination requests and successful responses are carried inside
|
|
|
104
104
|
protocol preflight uses its exact tag-only shape; `204` liveness and
|
|
105
105
|
acknowledgement responses are bodyless. Payload codecs are exported separately
|
|
106
106
|
so adapters can validate the envelope first and then validate the
|
|
107
|
-
operation-specific payload without accepting ambiguous fields.
|
|
107
|
+
operation-specific payload without accepting ambiguous fields. Append-log
|
|
108
|
+
requests require a canonical UUID `post_id`. Identity is scoped by authenticated
|
|
109
|
+
author: an exact retry must preserve the message and fully resolved visibility,
|
|
110
|
+
recipient set, and class routing, then returns the same entry with
|
|
111
|
+
`deduplicated: true`. Reusing an author's `post_id` with a changed tuple returns
|
|
112
|
+
`POST_ID_CONFLICT`; another author may independently use the same UUID. Attach responses include the nullable
|
|
113
|
+
`initial_log_cursor` that anchors subsequent log replay.
|
|
108
114
|
Cube managers reassign a seat with `PATCH /api/cubes/:cubeId/drones/:droneId`
|
|
109
115
|
and evict one with `DELETE` on the same path. Both operations use strict
|
|
110
116
|
versioned request and success envelopes. An evicted seat's former bearer receives
|
package/RELEASES.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
|
+
Eight published versions from 0.2.2 through 0.6.2, excluding the isolated 0.4.0
|
|
4
|
+
baseline, predate the canonical release-record convention. Historical incident
|
|
5
|
+
prose below remains their record instead of reconstructed structured entries.
|
|
6
|
+
|
|
3
7
|
`borgmcp-shared@0.4.0` is the published clean-slate v2 baseline and is
|
|
4
8
|
immutable, but its artifact predates the local/self-hosted package cleanup. The
|
|
5
9
|
immutable `v0.4.1` verification artifact exposed a platform-dependent SBOM audit
|
|
@@ -36,3 +40,13 @@ peels to protected-main commit `8e5bd088b8069951a687156c35cf68d44985ddc1`;
|
|
|
36
40
|
successful attempt-1 workflow run `31255563527` published registry integrity
|
|
37
41
|
`sha512-NYZJi6z0g/Txb6ge+5NgRPNRszVEi0eNmICxkoZq5bGkJWm5qEvNSt3ws90Xz8IOKuWcyHC9i6sAK6cbZxwYDw==`.
|
|
38
42
|
Never rerun or move that tag.
|
|
43
|
+
`borgmcp-shared@0.11.0` was published on 2026-08-11 and is immutable:
|
|
44
|
+
annotated tag `v0.11.0` peels to protected-main commit
|
|
45
|
+
`c1df96a858ff7c587d42508d388aa517a0b8545c`. PR #119 added the template
|
|
46
|
+
lifecycle document. PR #120 added local-model routing and ownership,
|
|
47
|
+
two-direction taxonomy agreement, the workflow-discipline mechanism split,
|
|
48
|
+
and minimalism completion. PR #121 added live-cube back-ports and the
|
|
49
|
+
external-surface single-owner directive rule. Successful attempt-1 workflow
|
|
50
|
+
run `31531549256` published registry integrity
|
|
51
|
+
`sha512-I8mixCbSrLKyOAAyqEI/HZJ8cML2rz3r812Up8pr547OdAk9LxZevdCo7ojG42ZwrUmS5u7iKQPg7Vk1XvtX1g==`.
|
|
52
|
+
Never rerun or move that tag.
|
|
@@ -131,6 +131,7 @@ export interface ConformanceAdmin {
|
|
|
131
131
|
readonly isMandatory?: boolean;
|
|
132
132
|
}): Promise<ConformanceRole>;
|
|
133
133
|
referenceRoleFromTaxonomy(cube: ConformanceCube, role: ConformanceRole): Promise<void>;
|
|
134
|
+
configureMessageClassRouting(cube: ConformanceCube, className: string, recipientDroneIds: readonly string[]): Promise<void>;
|
|
134
135
|
createDrone(principal: ConformancePrincipal, cube: ConformanceCube, role: ConformanceRole): Promise<ConformanceDrone>;
|
|
135
136
|
issueManagedDroneSession(drone: ConformanceDrone): Promise<string>;
|
|
136
137
|
revokeManagedDroneSession(drone: ConformanceDrone): Promise<void>;
|
|
@@ -210,6 +211,9 @@ export declare const ADAPTER_CONFORMANCE_FIXTURES: readonly [{
|
|
|
210
211
|
}, {
|
|
211
212
|
readonly id: "security.cross-cube-isolation";
|
|
212
213
|
readonly area: "security";
|
|
214
|
+
}, {
|
|
215
|
+
readonly id: "log.append-idempotency";
|
|
216
|
+
readonly area: "log";
|
|
213
217
|
}, {
|
|
214
218
|
readonly id: "log.read-cursor-tuple";
|
|
215
219
|
readonly area: "cursor";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/conformance/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EA8BL,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,YAAY,EAEjB,KAAK,SAAS,EAEd,KAAK,oBAAoB,EAC1B,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/conformance/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ErrorCode, compareLogCursor, createProtocolEnvelope, decodeAssociateRepositoryCubeResponseEnvelope, decodeCreateCubeResponseEnvelope, decodeDeleteCubeResponseEnvelope, decodeAppendLogResultEnvelope, decodeDecisionResultEnvelope, decodeDecisionsResultEnvelope, decodeEnrollmentExchangeResponseEnvelope, decodeInvitationArtifact, decodeAttachResponseEnvelope, decodeDroneRuntimeMetadataPatch, decodeEvictDroneResultEnvelope, decodeDeleteRoleResultEnvelope, decodeRoleRationaleResultEnvelope, decodeProtocolEnvelope, decodeProtocolErrorEnvelope, decodeProtocolTagPreflight, decodeReadLogResultEnvelope, decodeResolveRepositoryCubeResponseEnvelope, decodeReassignDroneResultEnvelope, decodeUpdateDroneRuntimeMetadataResponseEnvelope, decodeSseFrames, PROTOCOL_LIMIT_CEILINGS, PROTOCOL_HTTP_CONTRACT, PROTOCOL_VERSION, ROLE_IN_USE_DELETE_MESSAGE, utf8ByteLength, } from '../protocol/index.js';
|
|
2
|
-
import { CREATE_CUBE_ASSOCIATION_CONFORMANCE, CREATE_CUBE_RETRY_CONFORMANCE, INVITATION_ARTIFACT_CONFORMANCE, ENROLLMENT_RETRY_CONFORMANCE, } from './index.js';
|
|
2
|
+
import { APPEND_LOG_IDEMPOTENCY_CONFORMANCE, CREATE_CUBE_ASSOCIATION_CONFORMANCE, CREATE_CUBE_RETRY_CONFORMANCE, INVITATION_ARTIFACT_CONFORMANCE, ENROLLMENT_RETRY_CONFORMANCE, } from './index.js';
|
|
3
3
|
export const ADAPTER_CONFORMANCE_FIXTURES = [
|
|
4
4
|
{ id: 'http.unauthenticated-liveness', area: 'http' },
|
|
5
5
|
{ id: 'protocol.credential-free-preflight', area: 'protocol' },
|
|
@@ -9,6 +9,7 @@ export const ADAPTER_CONFORMANCE_FIXTURES = [
|
|
|
9
9
|
{ id: 'security.adapter-boundary-injection', area: 'security' },
|
|
10
10
|
{ id: 'security.oversize-request', area: 'security' },
|
|
11
11
|
{ id: 'security.cross-cube-isolation', area: 'security' },
|
|
12
|
+
{ id: 'log.append-idempotency', area: 'log' },
|
|
12
13
|
{ id: 'log.read-cursor-tuple', area: 'cursor' },
|
|
13
14
|
{ id: 'sse.replay-live-transition', area: 'sse' },
|
|
14
15
|
{ id: 'cursor.explicit-expiry', area: 'cursor' },
|
|
@@ -600,14 +601,20 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
600
601
|
});
|
|
601
602
|
await record('security.adapter-boundary-injection', async () => {
|
|
602
603
|
const injectedMessage = "'); DROP TABLE log_entries; --\r\ndata: forged-sse-frame";
|
|
603
|
-
const injectedBody = JSON.stringify(createProtocolEnvelope('inject-b1', {
|
|
604
|
+
const injectedBody = JSON.stringify(createProtocolEnvelope('inject-b1', {
|
|
605
|
+
post_id: '00000000-0000-4000-8000-000000000301',
|
|
606
|
+
message: injectedMessage,
|
|
607
|
+
}));
|
|
604
608
|
invariant(utf8ByteLength(injectedBody) <= PROTOCOL_LIMIT_CEILINGS.max_request_bytes &&
|
|
605
609
|
utf8ByteLength(injectedMessage) <= PROTOCOL_LIMIT_CEILINGS.max_log_message_bytes, 'Injection fixture exceeded the shared request-limit ceiling.');
|
|
606
610
|
const injected = await environment.operations.appendRaw(credentialB, cubeB, injectedBody);
|
|
607
611
|
expectStatus(injected, 201, 'Adapter-boundary injection append');
|
|
608
612
|
const injectedEntry = decodeAppendLogResultEnvelope(injected.body).payload.entry;
|
|
609
613
|
invariant(injectedEntry.message === injectedMessage, 'Adapter altered or interpreted injection-shaped log data.');
|
|
610
|
-
const sentinel = await environment.operations.append(credentialB, cubeB, createProtocolEnvelope('inject-b2', {
|
|
614
|
+
const sentinel = await environment.operations.append(credentialB, cubeB, createProtocolEnvelope('inject-b2', {
|
|
615
|
+
post_id: '00000000-0000-4000-8000-000000000302',
|
|
616
|
+
message: 'post-injection-sentinel',
|
|
617
|
+
}));
|
|
611
618
|
expectStatus(sentinel, 201, 'Post-injection sentinel append');
|
|
612
619
|
const read = await environment.operations.read(credentialB, cubeB, createProtocolEnvelope('inject-read', { cursor: null, limit: 10 }));
|
|
613
620
|
expectStatus(read, 200, 'Post-injection read');
|
|
@@ -636,7 +643,10 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
636
643
|
};
|
|
637
644
|
});
|
|
638
645
|
await record('security.oversize-request', async () => {
|
|
639
|
-
const baseBody = JSON.stringify(createProtocolEnvelope('oversize-a1', {
|
|
646
|
+
const baseBody = JSON.stringify(createProtocolEnvelope('oversize-a1', {
|
|
647
|
+
post_id: '00000000-0000-4000-8000-000000000303',
|
|
648
|
+
message: 'must-not-persist',
|
|
649
|
+
}));
|
|
640
650
|
const oversizedBody = baseBody + ' '.repeat(Math.max(0, PROTOCOL_LIMIT_CEILINGS.max_request_bytes - utf8ByteLength(baseBody) + 1));
|
|
641
651
|
invariant(utf8ByteLength(oversizedBody) > PROTOCOL_LIMIT_CEILINGS.max_request_bytes, 'Oversize fixture did not exceed max_request_bytes.');
|
|
642
652
|
const response = await environment.operations.appendRaw(credentialA, cubeA, oversizedBody);
|
|
@@ -647,17 +657,93 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
647
657
|
return { status: 413, code: ErrorCode.CONTENT_TOO_LARGE, persisted_entries: 0 };
|
|
648
658
|
});
|
|
649
659
|
await record('security.cross-cube-isolation', async () => {
|
|
650
|
-
const secretAppend = await environment.operations.append(credentialB, cubeB, createProtocolEnvelope('append-b1', {
|
|
660
|
+
const secretAppend = await environment.operations.append(credentialB, cubeB, createProtocolEnvelope('append-b1', {
|
|
661
|
+
post_id: '00000000-0000-4000-8000-000000000304',
|
|
662
|
+
message: 'principal-b-secret',
|
|
663
|
+
}));
|
|
651
664
|
expectStatus(secretAppend, 201, 'Principal B append');
|
|
652
665
|
const denied = await environment.operations.read(credentialA, cubeB, createProtocolEnvelope('read-cross', { cursor: null, limit: 10 }));
|
|
653
666
|
expectError(denied, 404, ErrorCode.NOT_FOUND, 'Cross-cube read');
|
|
654
667
|
return { status: 404, code: ErrorCode.NOT_FOUND };
|
|
655
668
|
});
|
|
669
|
+
await record('log.append-idempotency', async () => {
|
|
670
|
+
const principal = await environment.admin.createPrincipal('append-idempotency');
|
|
671
|
+
const otherPrincipal = await environment.admin.createPrincipal('append-idempotency-other');
|
|
672
|
+
const cube = await environment.admin.createCube('append-idempotency');
|
|
673
|
+
await environment.admin.grantCube(principal, cube);
|
|
674
|
+
await environment.admin.grantCube(otherPrincipal, cube);
|
|
675
|
+
const credential = await environment.admin.issueDroneSession(principal);
|
|
676
|
+
const otherCredential = await environment.admin.issueDroneSession(otherPrincipal);
|
|
677
|
+
const role = await environment.admin.createRole(cube, {
|
|
678
|
+
roleClass: 'worker',
|
|
679
|
+
isHumanSeat: false,
|
|
680
|
+
});
|
|
681
|
+
const firstRecipient = await environment.admin.createDrone(principal, cube, role);
|
|
682
|
+
const secondRecipient = await environment.admin.createDrone(principal, cube, role);
|
|
683
|
+
await environment.admin.configureMessageClassRouting(cube, 'conformance-review', [firstRecipient.id]);
|
|
684
|
+
await environment.admin.configureMessageClassRouting(cube, 'conformance-security', [firstRecipient.id]);
|
|
685
|
+
const postId = '00000000-0000-4000-8000-000000000313';
|
|
686
|
+
const initialPayload = {
|
|
687
|
+
post_id: postId,
|
|
688
|
+
message: 'once',
|
|
689
|
+
visibility: 'direct',
|
|
690
|
+
recipientDroneIds: [firstRecipient.id],
|
|
691
|
+
class: 'review',
|
|
692
|
+
to: ['Coordinator'],
|
|
693
|
+
};
|
|
694
|
+
const first = await environment.operations.append(credential, cube, createProtocolEnvelope('append-idempotency-first', initialPayload));
|
|
695
|
+
expectStatus(first, 201, 'Initial idempotent append');
|
|
696
|
+
const firstResult = decodeAppendLogResultEnvelope(first.body).payload;
|
|
697
|
+
invariant(!firstResult.deduplicated, 'Initial append was reported as deduplicated.');
|
|
698
|
+
for (const [index, vector] of APPEND_LOG_IDEMPOTENCY_CONFORMANCE.entries()) {
|
|
699
|
+
const classRouting = vector.mutation === 'resolved_class_routing';
|
|
700
|
+
const vectorPostId = classRouting
|
|
701
|
+
? '00000000-0000-4000-8000-000000000314'
|
|
702
|
+
: postId;
|
|
703
|
+
if (classRouting) {
|
|
704
|
+
const baseline = await environment.operations.append(credential, cube, createProtocolEnvelope('append-idempotency-class-baseline', {
|
|
705
|
+
post_id: vectorPostId,
|
|
706
|
+
message: 'once',
|
|
707
|
+
class: 'conformance-review',
|
|
708
|
+
}));
|
|
709
|
+
expectStatus(baseline, 201, 'Resolved class-routing baseline');
|
|
710
|
+
}
|
|
711
|
+
const payload = classRouting ? {
|
|
712
|
+
post_id: vectorPostId,
|
|
713
|
+
message: 'once',
|
|
714
|
+
class: 'conformance-security',
|
|
715
|
+
} : {
|
|
716
|
+
...initialPayload,
|
|
717
|
+
...(vector.mutation === 'message' ? { message: 'changed' } : {}),
|
|
718
|
+
...(vector.mutation === 'visibility' ? { visibility: 'broadcast' } : {}),
|
|
719
|
+
...(vector.mutation === 'recipient_set' ? { recipientDroneIds: [secondRecipient.id] } : {}),
|
|
720
|
+
...(vector.mutation === 'ignored_request_shape' ? { class: 'security', to: ['Security Auditor'] } : {}),
|
|
721
|
+
};
|
|
722
|
+
const response = await environment.operations.append(vector.actor === 'same' ? credential : otherCredential, cube, createProtocolEnvelope(`append-idempotency-${index}`, payload));
|
|
723
|
+
if (vector.expected === 'POST_ID_CONFLICT') {
|
|
724
|
+
expectError(response, 409, ErrorCode.POST_ID_CONFLICT, vector.name);
|
|
725
|
+
continue;
|
|
726
|
+
}
|
|
727
|
+
expectStatus(response, 201, vector.name);
|
|
728
|
+
const result = decodeAppendLogResultEnvelope(response.body).payload;
|
|
729
|
+
invariant(result.deduplicated === (vector.expected === 'deduplicated'), `${vector.name} returned the wrong deduplicated flag.`);
|
|
730
|
+
invariant(vector.expected === 'deduplicated'
|
|
731
|
+
? result.entry.id === firstResult.entry.id
|
|
732
|
+
: result.entry.id !== firstResult.entry.id, `${vector.name} returned the wrong entry identity.`);
|
|
733
|
+
}
|
|
734
|
+
const read = await environment.operations.read(credential, cube, createProtocolEnvelope('append-idempotency-read', { cursor: null, limit: 10 }));
|
|
735
|
+
expectStatus(read, 200, 'Idempotent append read');
|
|
736
|
+
invariant(decodeReadLogResultEnvelope(read.body).payload.entries.length === 3, 'Append collision controls persisted the wrong number of entries.');
|
|
737
|
+
return { persisted_entries: 3, stable_entry: true, deduplicated: true, conflicts: 4, cross_author_created: true };
|
|
738
|
+
});
|
|
656
739
|
const entries = [];
|
|
657
740
|
let readCursor = null;
|
|
658
741
|
await record('log.read-cursor-tuple', async () => {
|
|
659
742
|
for (const [index, message] of ['alpha', 'beta', 'gamma'].entries()) {
|
|
660
|
-
const response = await environment.operations.append(credentialA, cubeA, createProtocolEnvelope(`append-a${index + 1}`, {
|
|
743
|
+
const response = await environment.operations.append(credentialA, cubeA, createProtocolEnvelope(`append-a${index + 1}`, {
|
|
744
|
+
post_id: `00000000-0000-4000-8000-${String(305 + index).padStart(12, '0')}`,
|
|
745
|
+
message,
|
|
746
|
+
}));
|
|
661
747
|
expectStatus(response, 201, `Append ${message}`);
|
|
662
748
|
const entry = decodeAppendLogResultEnvelope(response.body).payload.entry;
|
|
663
749
|
entries.push({ id: entry.id, created_at: entry.created_at, message: entry.message });
|
|
@@ -679,7 +765,10 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
679
765
|
const openPromise = environment.operations.openStream(credentialA, cubeA, readCursor);
|
|
680
766
|
await within(barrier.reached, 'Replay transition boundary', streamDeadlineMs);
|
|
681
767
|
try {
|
|
682
|
-
const appendDelta = environment.operations.append(credentialA, cubeA, createProtocolEnvelope('append-a4', {
|
|
768
|
+
const appendDelta = environment.operations.append(credentialA, cubeA, createProtocolEnvelope('append-a4', {
|
|
769
|
+
post_id: '00000000-0000-4000-8000-000000000308',
|
|
770
|
+
message: 'delta',
|
|
771
|
+
}));
|
|
683
772
|
expectStatus(await appendDelta, 201, 'Transition append');
|
|
684
773
|
}
|
|
685
774
|
finally {
|
|
@@ -700,7 +789,10 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
700
789
|
invariant(bookmark.type === 'bookmark' && bookmark.replay_complete, 'Stream omitted its replay-complete bookmark.');
|
|
701
790
|
const noDuplicate = reader.next();
|
|
702
791
|
await provePending(noDuplicate, 'Live stream after delta', pendingProbeMs);
|
|
703
|
-
const epsilonResponse = await environment.operations.append(credentialA, cubeA, createProtocolEnvelope('append-a5', {
|
|
792
|
+
const epsilonResponse = await environment.operations.append(credentialA, cubeA, createProtocolEnvelope('append-a5', {
|
|
793
|
+
post_id: '00000000-0000-4000-8000-000000000309',
|
|
794
|
+
message: 'epsilon',
|
|
795
|
+
}));
|
|
704
796
|
expectStatus(epsilonResponse, 201, 'Live append');
|
|
705
797
|
const epsilon = logEvent(await within(noDuplicate, 'Live epsilon event', streamDeadlineMs), 'Live append');
|
|
706
798
|
invariant(epsilon.entry.message === 'epsilon', 'Live stream duplicated or reordered an event.');
|
|
@@ -970,6 +1062,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
970
1062
|
invariant(!listedDroneIds(after).includes(evictedDrone.id), 'Evicted drone remained in roster.');
|
|
971
1063
|
expectError(await environment.operations.append(credentialA, cubeA, createProtocolEnvelope('evict-direct-target', {
|
|
972
1064
|
message: 'must-not-fan-out',
|
|
1065
|
+
post_id: '00000000-0000-4000-8000-000000000310',
|
|
973
1066
|
visibility: 'direct',
|
|
974
1067
|
recipientDroneIds: [evictedDrone.id],
|
|
975
1068
|
})), 404, ErrorCode.NOT_FOUND, 'Evicted direct recipient');
|
|
@@ -1075,7 +1168,10 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
1075
1168
|
});
|
|
1076
1169
|
const evictedDrone = await environment.admin.createDrone(roleContractPrincipal, roleContractCube, evictedRole);
|
|
1077
1170
|
const evictedSession = await environment.admin.issueManagedDroneSession(evictedDrone);
|
|
1078
|
-
const attributed = await environment.operations.append(evictedSession, roleContractCube, createProtocolEnvelope('role-delete-attribution', {
|
|
1171
|
+
const attributed = await environment.operations.append(evictedSession, roleContractCube, createProtocolEnvelope('role-delete-attribution', {
|
|
1172
|
+
post_id: '00000000-0000-4000-8000-000000000311',
|
|
1173
|
+
message: 'attribution survives',
|
|
1174
|
+
}));
|
|
1079
1175
|
expectStatus(attributed, 201, 'Pre-delete attributed log');
|
|
1080
1176
|
const attributedEntry = decodeAppendLogResultEnvelope(attributed.body).payload.entry;
|
|
1081
1177
|
expectStatus(await environment.operations.evictDrone(roleContractCredential, roleContractCube, evictedDrone, createProtocolEnvelope('role-delete-evict', {})), 200, 'Pre-delete drone eviction');
|
|
@@ -1494,7 +1590,10 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
1494
1590
|
await environment.admin.grantCube(writer.principal, cube, 'write');
|
|
1495
1591
|
const drone = await environment.admin.createDrone(creator.principal, cube, role);
|
|
1496
1592
|
const droneCredential = await environment.admin.issueManagedDroneSession(drone);
|
|
1497
|
-
const append = await environment.operations.append(creator.credential, cube, createProtocolEnvelope('delete-log', {
|
|
1593
|
+
const append = await environment.operations.append(creator.credential, cube, createProtocolEnvelope('delete-log', {
|
|
1594
|
+
post_id: '00000000-0000-4000-8000-000000000312',
|
|
1595
|
+
message: 'deleted with cube',
|
|
1596
|
+
}));
|
|
1498
1597
|
expectStatus(append, 201, 'Deletion fixture log');
|
|
1499
1598
|
const entry = decodeAppendLogResultEnvelope(append.body).payload.entry;
|
|
1500
1599
|
expectStatus(await environment.operations.ack(creator.credential, cube, createProtocolEnvelope('delete-claim', { entry_id: entry.id, kind: 'claim' })), 204, 'Deletion fixture claim');
|