borgmcp-shared 0.13.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/RELEASES.md +7 -0
- package/dist/conformance/adapter.d.ts +15 -2
- package/dist/conformance/adapter.d.ts.map +1 -1
- package/dist/conformance/adapter.js +187 -41
- package/dist/conformance/adapter.js.map +1 -1
- package/dist/conformance/index.d.ts +49 -3
- package/dist/conformance/index.d.ts.map +1 -1
- package/dist/conformance/index.js +95 -18
- package/dist/conformance/index.js.map +1 -1
- package/dist/protocol/contract.d.ts +1 -1
- package/dist/protocol/contract.d.ts.map +1 -1
- package/dist/protocol/contract.js +13 -18
- package/dist/protocol/contract.js.map +1 -1
- package/dist/protocol/coordination.d.ts +36 -1
- package/dist/protocol/coordination.d.ts.map +1 -1
- package/dist/protocol/coordination.js +72 -6
- package/dist/protocol/coordination.js.map +1 -1
- package/dist/protocol/errors.d.ts +1 -1
- package/dist/protocol/errors.d.ts.map +1 -1
- package/dist/protocol/errors.js +1 -1
- package/dist/protocol/errors.js.map +1 -1
- package/dist/protocol/types.d.ts +1 -5
- 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/dist/templates.d.ts +1 -3
- package/dist/templates.d.ts.map +1 -1
- package/dist/templates.js +8 -79
- package/dist/templates.js.map +1 -1
- package/docs/compatibility.md +15 -0
- package/docs/release-records.json +28 -0
- package/docs/releases/0.14.0.md +8 -0
- package/docs/releases/1.0.0.md +11 -0
- package/docs/template-lifecycle.md +1 -1
- package/package.json +1 -1
- package/src/conformance/adapter.ts +369 -50
- package/src/conformance/index.ts +122 -22
- package/src/protocol/contract.ts +15 -21
- package/src/protocol/coordination.ts +136 -7
- package/src/protocol/errors.ts +1 -1
- package/src/protocol/types.ts +1 -5
- package/src/protocol/version.ts +2 -2
- package/src/templates.ts +8 -81
package/README.md
CHANGED
|
@@ -112,9 +112,10 @@ protocol preflight uses its exact tag-only shape; `204` liveness and
|
|
|
112
112
|
acknowledgement responses are bodyless. Payload codecs are exported separately
|
|
113
113
|
so adapters can validate the envelope first and then validate the
|
|
114
114
|
operation-specific payload without accepting ambiguous fields. Append-log
|
|
115
|
-
requests require a canonical UUID `post_id
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
requests require a canonical UUID `post_id` and an explicit `to` audience of
|
|
116
|
+
scalar `"broadcast"` or a non-empty recipient-selector array. Identity is scoped
|
|
117
|
+
by authenticated author: an exact retry must preserve the message and fully
|
|
118
|
+
resolved visibility and recipient set, then returns the same entry with
|
|
118
119
|
`deduplicated: true`. Reusing an author's `post_id` with a changed tuple returns
|
|
119
120
|
`POST_ID_CONFLICT`; another author may independently use the same UUID. Attach responses include the nullable
|
|
120
121
|
`initial_log_cursor` that anchors subsequent log replay.
|
package/RELEASES.md
CHANGED
|
@@ -74,3 +74,10 @@ Never rerun or move that tag.
|
|
|
74
74
|
the release live with registry integrity
|
|
75
75
|
`sha512-6t25in3kpkVZTQqbeP65HgObU8GpOY3ewtY2SoaHDtIcJEtoe1LRwh3rguE6VqcqPWBUtmXdOaTMdtBErx5+oA==`.
|
|
76
76
|
Never rerun or move that tag.
|
|
77
|
+
|
|
78
|
+
`borgmcp-shared@0.14.0` was published on 2026-08-16 and is immutable. Annotated
|
|
79
|
+
tag object `4ecd4e54bbf5a3dd719855ccc4d6f9db3939800f` peels to protected-main commit
|
|
80
|
+
`a69926023d53268131e95b63efd141a17c634e2d`; successful attempt-1 workflow run
|
|
81
|
+
`31957839605` published registry integrity
|
|
82
|
+
`sha512-rKRMxnxTnW+o3WOqtAFoih9IeRKCZw/lltqz7CbjC1riNq52CsZ871o1Fo7Fdk0WqwuzdFQmRJ7qOzPi08Q/QA==`.
|
|
83
|
+
Never rerun or move that tag.
|
|
@@ -60,6 +60,9 @@ export interface ConformanceCubeManagementState {
|
|
|
60
60
|
export interface ConformanceAuthorityState {
|
|
61
61
|
enrolled_clients: number;
|
|
62
62
|
enrollment_claims: number;
|
|
63
|
+
activity_acknowledgements: number;
|
|
64
|
+
activity_claims: number;
|
|
65
|
+
activity_log_entries: number;
|
|
63
66
|
cubes: number;
|
|
64
67
|
roles: number;
|
|
65
68
|
grants: number;
|
|
@@ -130,8 +133,7 @@ export interface ConformanceAdmin {
|
|
|
130
133
|
readonly isDefault?: boolean;
|
|
131
134
|
readonly isMandatory?: boolean;
|
|
132
135
|
}): Promise<ConformanceRole>;
|
|
133
|
-
|
|
134
|
-
configureMessageClassRouting(cube: ConformanceCube, className: string, recipientDroneIds: readonly string[]): Promise<void>;
|
|
136
|
+
replaceLogEntryId(cube: ConformanceCube, currentId: string, replacementId: string): Promise<void>;
|
|
135
137
|
createDrone(principal: ConformancePrincipal, cube: ConformanceCube, role: ConformanceRole): Promise<ConformanceDrone>;
|
|
136
138
|
issueManagedDroneSession(drone: ConformanceDrone): Promise<string>;
|
|
137
139
|
revokeManagedDroneSession(drone: ConformanceDrone): Promise<void>;
|
|
@@ -174,7 +176,9 @@ export interface ConformanceOperations {
|
|
|
174
176
|
append(credential: string, cube: ConformanceCube, request: unknown): Promise<ConformanceHttpResponse>;
|
|
175
177
|
appendRaw(credential: string, cube: ConformanceCube, body: string): Promise<ConformanceHttpResponse>;
|
|
176
178
|
read(credential: string, cube: ConformanceCube, request: unknown): Promise<ConformanceHttpResponse>;
|
|
179
|
+
entryQuery(credential: string, cube: ConformanceCube, request: unknown): Promise<ConformanceHttpResponse>;
|
|
177
180
|
ack(credential: string, cube: ConformanceCube, request: unknown): Promise<ConformanceHttpResponse>;
|
|
181
|
+
ackStatus(credential: string, cube: ConformanceCube, request: unknown): Promise<ConformanceHttpResponse>;
|
|
178
182
|
updateCube(credential: string, cube: ConformanceCube, request: unknown): Promise<ConformanceHttpResponse>;
|
|
179
183
|
createRole(credential: string, cube: ConformanceCube, request: unknown): Promise<ConformanceHttpResponse>;
|
|
180
184
|
patchTaxonomy(credential: string, cube: ConformanceCube, request: unknown): Promise<ConformanceHttpResponse>;
|
|
@@ -221,6 +225,12 @@ export declare const ADAPTER_CONFORMANCE_FIXTURES: readonly [{
|
|
|
221
225
|
}, {
|
|
222
226
|
readonly id: "log.append-idempotency";
|
|
223
227
|
readonly area: "log";
|
|
228
|
+
}, {
|
|
229
|
+
readonly id: "log.mandatory-addressing";
|
|
230
|
+
readonly area: "log";
|
|
231
|
+
}, {
|
|
232
|
+
readonly id: "log.entry-query";
|
|
233
|
+
readonly area: "log";
|
|
224
234
|
}, {
|
|
225
235
|
readonly id: "log.read-cursor-tuple";
|
|
226
236
|
readonly area: "cursor";
|
|
@@ -233,6 +243,9 @@ export declare const ADAPTER_CONFORMANCE_FIXTURES: readonly [{
|
|
|
233
243
|
}, {
|
|
234
244
|
readonly id: "acks.idempotent";
|
|
235
245
|
readonly area: "acks";
|
|
246
|
+
}, {
|
|
247
|
+
readonly id: "acks.status-query";
|
|
248
|
+
readonly area: "acks";
|
|
236
249
|
}, {
|
|
237
250
|
readonly id: "claims.durable-noncursor";
|
|
238
251
|
readonly area: "claims";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/conformance/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
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, decodeAssociateRepositoryCubeResponseEnvelope, decodeCreateCubeResponseEnvelope, decodeDeleteCubeResponseEnvelope, decodeAppendLogResultEnvelope, decodeDecisionResultEnvelope, decodeDecisionsResultEnvelope, decodeEnrollmentExchangeResponseEnvelope, decodeInvitationArtifact, decodeAttachResponseEnvelope, decodeDroneRuntimeMetadataPatch, decodeEvictDroneResultEnvelope, decodeDeleteRoleResultEnvelope, decodeRoleRationaleResultEnvelope, decodeProtocolEnvelope, decodeProtocolErrorEnvelope, decodeProtocolTagPreflight, decodeReadLogResultEnvelope, decodeResolveRepositoryCubeResponseEnvelope, decodeReassignDroneResultEnvelope, decodeUpdateDroneRuntimeMetadataResponseEnvelope, decodeGetDocumentResultEnvelope, decodeListDocumentsResultEnvelope, decodePutDocumentResultEnvelope, decodeRemoveDocumentResultEnvelope, decodeSseFrames, PROTOCOL_LIMIT_CEILINGS, PROTOCOL_HTTP_CONTRACT, PROTOCOL_VERSION, ROLE_IN_USE_DELETE_MESSAGE, utf8ByteLength, } from '../protocol/index.js';
|
|
1
|
+
import { ErrorCode, compareLogCursor, createProtocolEnvelope, decodeAssociateRepositoryCubeResponseEnvelope, decodeCreateCubeResponseEnvelope, decodeDeleteCubeResponseEnvelope, decodeAppendLogResultEnvelope, decodeAckStatusResultEnvelope, decodeEntryQueryResultEnvelope, decodeDecisionResultEnvelope, decodeDecisionsResultEnvelope, decodeEnrollmentExchangeResponseEnvelope, decodeInvitationArtifact, decodeAttachResponseEnvelope, decodeDroneRuntimeMetadataPatch, decodeEvictDroneResultEnvelope, decodeDeleteRoleResultEnvelope, decodeRoleRationaleResultEnvelope, decodeProtocolEnvelope, decodeProtocolErrorEnvelope, decodeProtocolTagPreflight, decodeReadLogResultEnvelope, decodeResolveRepositoryCubeResponseEnvelope, decodeReassignDroneResultEnvelope, decodeUpdateDroneRuntimeMetadataResponseEnvelope, decodeGetDocumentResultEnvelope, decodeListDocumentsResultEnvelope, decodePutDocumentResultEnvelope, decodeRemoveDocumentResultEnvelope, decodeSseFrames, PROTOCOL_LIMIT_CEILINGS, PROTOCOL_HTTP_CONTRACT, PROTOCOL_VERSION, ROLE_IN_USE_DELETE_MESSAGE, utf8ByteLength, } from '../protocol/index.js';
|
|
2
2
|
import { APPEND_LOG_IDEMPOTENCY_CONFORMANCE, CREATE_CUBE_ASSOCIATION_CONFORMANCE, CREATE_CUBE_RETRY_CONFORMANCE, INVITATION_ARTIFACT_CONFORMANCE, ENROLLMENT_RETRY_CONFORMANCE, DOCUMENT_CONFORMANCE, } from './index.js';
|
|
3
3
|
export const ADAPTER_CONFORMANCE_FIXTURES = [
|
|
4
4
|
{ id: 'http.unauthenticated-liveness', area: 'http' },
|
|
@@ -11,10 +11,13 @@ export const ADAPTER_CONFORMANCE_FIXTURES = [
|
|
|
11
11
|
{ id: 'security.oversize-request', area: 'security' },
|
|
12
12
|
{ id: 'security.cross-cube-isolation', area: 'security' },
|
|
13
13
|
{ id: 'log.append-idempotency', area: 'log' },
|
|
14
|
+
{ id: 'log.mandatory-addressing', area: 'log' },
|
|
15
|
+
{ id: 'log.entry-query', area: 'log' },
|
|
14
16
|
{ id: 'log.read-cursor-tuple', area: 'cursor' },
|
|
15
17
|
{ id: 'sse.replay-live-transition', area: 'sse' },
|
|
16
18
|
{ id: 'cursor.explicit-expiry', area: 'cursor' },
|
|
17
19
|
{ id: 'acks.idempotent', area: 'acks' },
|
|
20
|
+
{ id: 'acks.status-query', area: 'acks' },
|
|
18
21
|
{ id: 'claims.durable-noncursor', area: 'claims' },
|
|
19
22
|
{ id: 'decisions.topic-supersession', area: 'decisions' },
|
|
20
23
|
{ id: 'security.drone-management-authorization', area: 'security' },
|
|
@@ -667,6 +670,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
667
670
|
const entriesBeforeForeignCitation = decodeReadLogResultEnvelope((await environment.operations.read(documentCredential, documentCube, createProtocolEnvelope('document-read-before-foreign-cite', { cursor: null, limit: 100 }))).body).payload.entries.length;
|
|
668
671
|
expectSecretFreeError(await environment.operations.append(documentCredential, documentCube, createProtocolEnvelope('document-foreign-citation', {
|
|
669
672
|
post_id: '00000000-0000-4000-8000-00000000031f',
|
|
673
|
+
to: 'broadcast',
|
|
670
674
|
message: 'Foreign evidence must remain hidden.',
|
|
671
675
|
documents: [foreignDocument.id],
|
|
672
676
|
})), 404, ErrorCode.DOCUMENT_NOT_FOUND, 'Foreign document citation', [foreignDocument.title, foreignDocument.content]);
|
|
@@ -686,6 +690,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
686
690
|
expectError(await environment.operations.putDocument(credentialA, cubeA, createProtocolEnvelope('document-cross-cube', { title: 'Cross cube', content_type: 'text/plain', content: 'x', supersedes: created.id })), 409, ErrorCode.DOCUMENT_SUPERSESSION_INVALID, 'Cross-cube document supersession');
|
|
687
691
|
const citationResponse = await environment.operations.append(documentCredential, documentCube, createProtocolEnvelope('document-citation', {
|
|
688
692
|
post_id: '00000000-0000-4000-8000-000000000320',
|
|
693
|
+
to: 'broadcast',
|
|
689
694
|
message: 'See the document evidence.',
|
|
690
695
|
documents: [created.id, successor.id],
|
|
691
696
|
}));
|
|
@@ -694,6 +699,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
694
699
|
invariant(cited?.length === 2 && cited[0].state === 'superseded', 'Log citations did not render document metadata and state.');
|
|
695
700
|
expectError(await environment.operations.append(documentCredential, documentCube, createProtocolEnvelope('document-citation-conflict', {
|
|
696
701
|
post_id: '00000000-0000-4000-8000-000000000320',
|
|
702
|
+
to: 'broadcast',
|
|
697
703
|
message: 'See the document evidence.',
|
|
698
704
|
documents: [successor.id],
|
|
699
705
|
})), 409, ErrorCode.POST_ID_CONFLICT, 'Document citation post-id conflict');
|
|
@@ -734,15 +740,15 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
734
740
|
const entriesBeforeUnknownCitation = (await environment.operations.read(documentCredential, documentCube, createProtocolEnvelope('document-read-before-unknown-cite', { cursor: null, limit: 100 })));
|
|
735
741
|
const beforeCount = decodeReadLogResultEnvelope(entriesBeforeUnknownCitation.body).payload.entries.length;
|
|
736
742
|
expectError(await environment.operations.append(documentCredential, documentCube, createProtocolEnvelope('document-unknown-citation', {
|
|
737
|
-
post_id: '00000000-0000-4000-8000-000000000321', message: 'Unknown.', documents: ['unknown_full_id'],
|
|
743
|
+
post_id: '00000000-0000-4000-8000-000000000321', message: 'Unknown.', to: 'broadcast', documents: ['unknown_full_id'],
|
|
738
744
|
})), 404, ErrorCode.DOCUMENT_NOT_FOUND, 'Unknown document citation');
|
|
739
745
|
const longAccepted = await environment.operations.append(documentCredential, documentCube, createProtocolEnvelope('document-advisory', {
|
|
740
|
-
post_id: '00000000-0000-4000-8000-000000000322', message: 'x'.repeat(1025),
|
|
746
|
+
post_id: '00000000-0000-4000-8000-000000000322', message: 'x'.repeat(1025), to: 'broadcast',
|
|
741
747
|
}));
|
|
742
748
|
expectStatus(longAccepted, 201, 'Advisory log append');
|
|
743
749
|
invariant(decodeAppendLogResultEnvelope(longAccepted.body).payload.advisory?.threshold_bytes === 1024, 'Configured advisory was not returned.');
|
|
744
750
|
expectError(await environment.operations.append(documentCredential, documentCube, createProtocolEnvelope('document-hard-cap', {
|
|
745
|
-
post_id: '00000000-0000-4000-8000-000000000323', message: 'x'.repeat(4097),
|
|
751
|
+
post_id: '00000000-0000-4000-8000-000000000323', message: 'x'.repeat(4097), to: 'broadcast',
|
|
746
752
|
})), 413, ErrorCode.CONTENT_TOO_LARGE, 'Hard-cap log append');
|
|
747
753
|
const citedRead = decodeReadLogResultEnvelope((await environment.operations.read(documentCredential, documentCube, createProtocolEnvelope('document-citation-read', { cursor: null, limit: 10 }))).body).payload.entries[0].documents;
|
|
748
754
|
invariant(citedRead?.[0].state === 'removed', 'Log citation did not resolve the audit-retained removed state.');
|
|
@@ -757,6 +763,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
757
763
|
const injectedMessage = "'); DROP TABLE log_entries; --\r\ndata: forged-sse-frame";
|
|
758
764
|
const injectedBody = JSON.stringify(createProtocolEnvelope('inject-b1', {
|
|
759
765
|
post_id: '00000000-0000-4000-8000-000000000301',
|
|
766
|
+
to: 'broadcast',
|
|
760
767
|
message: injectedMessage,
|
|
761
768
|
}));
|
|
762
769
|
invariant(utf8ByteLength(injectedBody) <= PROTOCOL_LIMIT_CEILINGS.max_request_bytes &&
|
|
@@ -767,6 +774,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
767
774
|
invariant(injectedEntry.message === injectedMessage, 'Adapter altered or interpreted injection-shaped log data.');
|
|
768
775
|
const sentinel = await environment.operations.append(credentialB, cubeB, createProtocolEnvelope('inject-b2', {
|
|
769
776
|
post_id: '00000000-0000-4000-8000-000000000302',
|
|
777
|
+
to: 'broadcast',
|
|
770
778
|
message: 'post-injection-sentinel',
|
|
771
779
|
}));
|
|
772
780
|
expectStatus(sentinel, 201, 'Post-injection sentinel append');
|
|
@@ -799,6 +807,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
799
807
|
await record('security.oversize-request', async () => {
|
|
800
808
|
const baseBody = JSON.stringify(createProtocolEnvelope('oversize-a1', {
|
|
801
809
|
post_id: '00000000-0000-4000-8000-000000000303',
|
|
810
|
+
to: 'broadcast',
|
|
802
811
|
message: 'must-not-persist',
|
|
803
812
|
}));
|
|
804
813
|
const oversizedBody = baseBody + ' '.repeat(Math.max(0, PROTOCOL_LIMIT_CEILINGS.max_request_bytes - utf8ByteLength(baseBody) + 1));
|
|
@@ -814,6 +823,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
814
823
|
const secretAppend = await environment.operations.append(credentialB, cubeB, createProtocolEnvelope('append-b1', {
|
|
815
824
|
post_id: '00000000-0000-4000-8000-000000000304',
|
|
816
825
|
message: 'principal-b-secret',
|
|
826
|
+
to: 'broadcast',
|
|
817
827
|
}));
|
|
818
828
|
expectStatus(secretAppend, 201, 'Principal B append');
|
|
819
829
|
const denied = await environment.operations.read(credentialA, cubeB, createProtocolEnvelope('read-cross', { cursor: null, limit: 10 }));
|
|
@@ -834,44 +844,24 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
834
844
|
});
|
|
835
845
|
const firstRecipient = await environment.admin.createDrone(principal, cube, role);
|
|
836
846
|
const secondRecipient = await environment.admin.createDrone(principal, cube, role);
|
|
837
|
-
await environment.admin.configureMessageClassRouting(cube, 'conformance-review', [firstRecipient.id]);
|
|
838
|
-
await environment.admin.configureMessageClassRouting(cube, 'conformance-security', [firstRecipient.id]);
|
|
839
847
|
const postId = '00000000-0000-4000-8000-000000000313';
|
|
840
848
|
const initialPayload = {
|
|
841
849
|
post_id: postId,
|
|
842
850
|
message: 'once',
|
|
843
|
-
|
|
844
|
-
recipientDroneIds: [firstRecipient.id],
|
|
851
|
+
to: [firstRecipient.id],
|
|
845
852
|
class: 'review',
|
|
846
|
-
to: ['Coordinator'],
|
|
847
853
|
};
|
|
848
854
|
const first = await environment.operations.append(credential, cube, createProtocolEnvelope('append-idempotency-first', initialPayload));
|
|
849
855
|
expectStatus(first, 201, 'Initial idempotent append');
|
|
850
856
|
const firstResult = decodeAppendLogResultEnvelope(first.body).payload;
|
|
851
857
|
invariant(!firstResult.deduplicated, 'Initial append was reported as deduplicated.');
|
|
852
858
|
for (const [index, vector] of APPEND_LOG_IDEMPOTENCY_CONFORMANCE.entries()) {
|
|
853
|
-
const
|
|
854
|
-
const vectorPostId = classRouting
|
|
855
|
-
? '00000000-0000-4000-8000-000000000314'
|
|
856
|
-
: postId;
|
|
857
|
-
if (classRouting) {
|
|
858
|
-
const baseline = await environment.operations.append(credential, cube, createProtocolEnvelope('append-idempotency-class-baseline', {
|
|
859
|
-
post_id: vectorPostId,
|
|
860
|
-
message: 'once',
|
|
861
|
-
class: 'conformance-review',
|
|
862
|
-
}));
|
|
863
|
-
expectStatus(baseline, 201, 'Resolved class-routing baseline');
|
|
864
|
-
}
|
|
865
|
-
const payload = classRouting ? {
|
|
866
|
-
post_id: vectorPostId,
|
|
867
|
-
message: 'once',
|
|
868
|
-
class: 'conformance-security',
|
|
869
|
-
} : {
|
|
859
|
+
const payload = {
|
|
870
860
|
...initialPayload,
|
|
871
861
|
...(vector.mutation === 'message' ? { message: 'changed' } : {}),
|
|
872
|
-
...(vector.mutation === '
|
|
873
|
-
...(vector.mutation === 'recipient_set' ? {
|
|
874
|
-
...(vector.mutation === '
|
|
862
|
+
...(vector.mutation === 'audience' ? { to: 'broadcast' } : {}),
|
|
863
|
+
...(vector.mutation === 'recipient_set' ? { to: [secondRecipient.id] } : {}),
|
|
864
|
+
...(vector.mutation === 'classification' ? { class: 'security' } : {}),
|
|
875
865
|
};
|
|
876
866
|
const response = await environment.operations.append(vector.actor === 'same' ? credential : otherCredential, cube, createProtocolEnvelope(`append-idempotency-${index}`, payload));
|
|
877
867
|
if (vector.expected === 'POST_ID_CONFLICT') {
|
|
@@ -887,8 +877,109 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
887
877
|
}
|
|
888
878
|
const read = await environment.operations.read(credential, cube, createProtocolEnvelope('append-idempotency-read', { cursor: null, limit: 10 }));
|
|
889
879
|
expectStatus(read, 200, 'Idempotent append read');
|
|
890
|
-
invariant(decodeReadLogResultEnvelope(read.body).payload.entries.length ===
|
|
891
|
-
return { persisted_entries:
|
|
880
|
+
invariant(decodeReadLogResultEnvelope(read.body).payload.entries.length === 2, 'Append collision controls persisted the wrong number of entries.');
|
|
881
|
+
return { persisted_entries: 2, stable_entry: true, deduplicated: true, conflicts: 3, cross_author_created: true };
|
|
882
|
+
});
|
|
883
|
+
await record('log.mandatory-addressing', async () => {
|
|
884
|
+
const cube = await environment.admin.createCube('mandatory-addressing-cube');
|
|
885
|
+
await environment.admin.grantCube(principalA, cube);
|
|
886
|
+
const role = await environment.admin.createRole(cube, {
|
|
887
|
+
roleClass: 'worker',
|
|
888
|
+
isHumanSeat: false,
|
|
889
|
+
name: 'Structured Recipient',
|
|
890
|
+
});
|
|
891
|
+
const recipient = await environment.admin.createDrone(principalA, cube, role);
|
|
892
|
+
const message = 'START NOW exact slice';
|
|
893
|
+
const before = await environment.admin.observeAuthorityState();
|
|
894
|
+
expectError(await environment.operations.append(credentialA, cube, createProtocolEnvelope('mandatory-addressing-omitted', {
|
|
895
|
+
post_id: '30000000-0000-4000-8000-000000000001',
|
|
896
|
+
message,
|
|
897
|
+
})), 400, ErrorCode.INVALID_INPUT, 'Omitted mandatory addressing');
|
|
898
|
+
assertStateDelta(before, await environment.admin.observeAuthorityState(), {}, 'Mandatory-addressing refusal');
|
|
899
|
+
const broadcast = await environment.operations.append(credentialA, cube, createProtocolEnvelope('mandatory-addressing-broadcast', {
|
|
900
|
+
post_id: '30000000-0000-4000-8000-000000000002',
|
|
901
|
+
message,
|
|
902
|
+
to: 'broadcast',
|
|
903
|
+
}));
|
|
904
|
+
expectStatus(broadcast, 201, 'Explicit broadcast addressing');
|
|
905
|
+
const broadcastResult = decodeAppendLogResultEnvelope(broadcast.body).payload;
|
|
906
|
+
invariant(broadcastResult.entry.visibility === 'broadcast', 'Scalar broadcast did not produce broadcast visibility.');
|
|
907
|
+
invariant((broadcastResult.entry.recipient_drone_ids?.length ?? 0) === 0, 'Scalar broadcast unexpectedly resolved direct recipients.');
|
|
908
|
+
const directed = await environment.operations.append(credentialA, cube, createProtocolEnvelope('mandatory-addressing-directed', {
|
|
909
|
+
post_id: '30000000-0000-4000-8000-000000000003',
|
|
910
|
+
message,
|
|
911
|
+
to: [recipient.id],
|
|
912
|
+
class: 'cube-wide',
|
|
913
|
+
}));
|
|
914
|
+
expectStatus(directed, 201, 'Recipient-selector union branch');
|
|
915
|
+
const directedResult = decodeAppendLogResultEnvelope(directed.body).payload;
|
|
916
|
+
invariant(directedResult.entry.visibility === 'direct', 'Explicit recipient selectors did not produce direct visibility.');
|
|
917
|
+
invariant(directedResult.entry.recipient_drone_ids?.includes(recipient.id) === true, 'Explicit recipient selectors did not resolve the named recipient.');
|
|
918
|
+
invariant(directedResult.entry.recipient_drone_ids?.length === 1, 'Classification changed or fell open the explicit recipient set.');
|
|
919
|
+
return { refused_status: 400, code: ErrorCode.INVALID_INPUT, persisted: false, broadcast: true, union: true, no_fall_open: true };
|
|
920
|
+
});
|
|
921
|
+
await record('log.entry-query', async () => {
|
|
922
|
+
const cube = await environment.admin.createCube('entry-query-cube');
|
|
923
|
+
await environment.admin.grantCube(principalA, cube);
|
|
924
|
+
const role = await environment.admin.createRole(cube, {
|
|
925
|
+
roleClass: 'worker',
|
|
926
|
+
isHumanSeat: false,
|
|
927
|
+
name: 'Entry Query Worker',
|
|
928
|
+
});
|
|
929
|
+
const acknowledgedRecipient = await environment.admin.createDrone(principalA, cube, role);
|
|
930
|
+
const claimingRecipient = await environment.admin.createDrone(principalA, cube, role);
|
|
931
|
+
const acknowledgedCredential = await environment.admin.issueManagedDroneSession(acknowledgedRecipient);
|
|
932
|
+
const claimingCredential = await environment.admin.issueManagedDroneSession(claimingRecipient);
|
|
933
|
+
const ids = [
|
|
934
|
+
'11111111-0000-4000-8000-000000000001',
|
|
935
|
+
'22222222-0000-4000-8000-000000000001',
|
|
936
|
+
'22222222-0000-4000-8000-000000000002',
|
|
937
|
+
];
|
|
938
|
+
const entries = [];
|
|
939
|
+
for (const [index, id] of ids.entries()) {
|
|
940
|
+
const response = await environment.operations.append(credentialA, cube, createProtocolEnvelope(`entry-query-append-${index}`, {
|
|
941
|
+
post_id: `40000000-0000-4000-8000-00000000000${index}`,
|
|
942
|
+
to: [acknowledgedRecipient.id, claimingRecipient.id],
|
|
943
|
+
message: `entry-query-${index}`,
|
|
944
|
+
}));
|
|
945
|
+
expectStatus(response, 201, `Entry-query fixture append ${index}`);
|
|
946
|
+
const entry = decodeAppendLogResultEnvelope(response.body).payload.entry;
|
|
947
|
+
await environment.admin.replaceLogEntryId(cube, entry.id, id);
|
|
948
|
+
entries.push({ ...entry, id });
|
|
949
|
+
}
|
|
950
|
+
expectStatus(await environment.operations.ack(acknowledgedCredential, cube, createProtocolEnvelope('entry-query-seed-ack', { entry_id: ids[0], kind: 'ack' })), 204, 'Entry-query acknowledgement seed');
|
|
951
|
+
expectStatus(await environment.operations.ack(claimingCredential, cube, createProtocolEnvelope('entry-query-seed-claim', { entry_id: ids[1], kind: 'claim' })), 204, 'Entry-query claim seed');
|
|
952
|
+
const before = await environment.admin.observeAuthorityState();
|
|
953
|
+
for (const [requestId, selector, expectedId] of [
|
|
954
|
+
['entry-query-full', ids[1], ids[1]],
|
|
955
|
+
['entry-query-prefix', '11111111', ids[0]],
|
|
956
|
+
]) {
|
|
957
|
+
const response = await environment.operations.entryQuery(credentialA, cube, createProtocolEnvelope(requestId, { entry_id: selector }));
|
|
958
|
+
expectStatus(response, 200, requestId);
|
|
959
|
+
const result = decodeEntryQueryResultEnvelope(response.body).payload;
|
|
960
|
+
invariant(result.entry.id === expectedId, `${requestId} returned the wrong entry.`);
|
|
961
|
+
}
|
|
962
|
+
expectError(await environment.operations.entryQuery(credentialA, cube, createProtocolEnvelope('entry-query-unknown', { entry_id: 'ffffffff' })), 404, ErrorCode.NOT_FOUND, 'Unknown entry query');
|
|
963
|
+
expectError(await environment.operations.entryQuery(credentialA, cube, createProtocolEnvelope('entry-query-ambiguous', { entry_id: '22222222' })), 409, ErrorCode.LOG_ENTRY_PREFIX_AMBIGUOUS, 'Ambiguous entry query');
|
|
964
|
+
assertStateDelta(before, await environment.admin.observeAuthorityState(), {}, 'Entry query');
|
|
965
|
+
const acknowledgementStatus = decodeAckStatusResultEnvelope((await environment.operations.ackStatus(credentialA, cube, createProtocolEnvelope('entry-query-ack-status', { entry_id: ids[0] }))).body).payload;
|
|
966
|
+
const claimStatus = decodeAckStatusResultEnvelope((await environment.operations.ackStatus(credentialA, cube, createProtocolEnvelope('entry-query-claim-status', { entry_id: ids[1] }))).body).payload;
|
|
967
|
+
invariant(acknowledgementStatus.recipients.some((recipient) => recipient.drone_id === acknowledgedRecipient.id && recipient.acknowledged_at !== null), 'Entry query removed the seeded acknowledgement.');
|
|
968
|
+
invariant(claimStatus.claims.some((claim) => claim.drone_id === claimingRecipient.id), 'Entry query removed the seeded claim.');
|
|
969
|
+
const unreadResponse = await environment.operations.read(credentialA, cube, createProtocolEnvelope('entry-query-unread', { cursor: null, limit: 10 }));
|
|
970
|
+
expectStatus(unreadResponse, 200, 'Entry-query unread read');
|
|
971
|
+
const unread = decodeReadLogResultEnvelope(unreadResponse.body).payload;
|
|
972
|
+
invariant(unread.entries.length === entries.length && entries.every((entry) => unread.entries.some((item) => item.id === entry.id)), 'Entry query consumed or advanced unread activity.');
|
|
973
|
+
return {
|
|
974
|
+
full_uuid: true,
|
|
975
|
+
unique_prefix: true,
|
|
976
|
+
ambiguous_code: ErrorCode.LOG_ENTRY_PREFIX_AMBIGUOUS,
|
|
977
|
+
unknown_code: ErrorCode.NOT_FOUND,
|
|
978
|
+
unread_entry_available: true,
|
|
979
|
+
acknowledgement_preserved: true,
|
|
980
|
+
claim_preserved: true,
|
|
981
|
+
mutation: 'none',
|
|
982
|
+
};
|
|
892
983
|
});
|
|
893
984
|
const entries = [];
|
|
894
985
|
let readCursor = null;
|
|
@@ -896,6 +987,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
896
987
|
for (const [index, message] of ['alpha', 'beta', 'gamma'].entries()) {
|
|
897
988
|
const response = await environment.operations.append(credentialA, cubeA, createProtocolEnvelope(`append-a${index + 1}`, {
|
|
898
989
|
post_id: `00000000-0000-4000-8000-${String(305 + index).padStart(12, '0')}`,
|
|
990
|
+
to: 'broadcast',
|
|
899
991
|
message,
|
|
900
992
|
}));
|
|
901
993
|
expectStatus(response, 201, `Append ${message}`);
|
|
@@ -921,6 +1013,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
921
1013
|
try {
|
|
922
1014
|
const appendDelta = environment.operations.append(credentialA, cubeA, createProtocolEnvelope('append-a4', {
|
|
923
1015
|
post_id: '00000000-0000-4000-8000-000000000308',
|
|
1016
|
+
to: 'broadcast',
|
|
924
1017
|
message: 'delta',
|
|
925
1018
|
}));
|
|
926
1019
|
expectStatus(await appendDelta, 201, 'Transition append');
|
|
@@ -945,6 +1038,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
945
1038
|
await provePending(noDuplicate, 'Live stream after delta', pendingProbeMs);
|
|
946
1039
|
const epsilonResponse = await environment.operations.append(credentialA, cubeA, createProtocolEnvelope('append-a5', {
|
|
947
1040
|
post_id: '00000000-0000-4000-8000-000000000309',
|
|
1041
|
+
to: 'broadcast',
|
|
948
1042
|
message: 'epsilon',
|
|
949
1043
|
}));
|
|
950
1044
|
expectStatus(epsilonResponse, 201, 'Live append');
|
|
@@ -979,6 +1073,65 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
979
1073
|
invariant((first.body === '' || first.body === undefined) && (second.body === '' || second.body === undefined), 'Acknowledgement responses must be bodyless.');
|
|
980
1074
|
return { first_status: 204, repeated_status: 204, bodyless: true };
|
|
981
1075
|
});
|
|
1076
|
+
await record('acks.status-query', async () => {
|
|
1077
|
+
const cube = await environment.admin.createCube('ack-status-cube');
|
|
1078
|
+
await environment.admin.grantCube(principalA, cube);
|
|
1079
|
+
const role = await environment.admin.createRole(cube, {
|
|
1080
|
+
roleClass: 'worker',
|
|
1081
|
+
isHumanSeat: false,
|
|
1082
|
+
name: 'Ack Status Worker',
|
|
1083
|
+
});
|
|
1084
|
+
const acknowledgedRecipient = await environment.admin.createDrone(principalA, cube, role);
|
|
1085
|
+
const claimingRecipient = await environment.admin.createDrone(principalA, cube, role);
|
|
1086
|
+
const acknowledgedCredential = await environment.admin.issueManagedDroneSession(acknowledgedRecipient);
|
|
1087
|
+
const claimingCredential = await environment.admin.issueManagedDroneSession(claimingRecipient);
|
|
1088
|
+
const append = await environment.operations.append(credentialA, cube, createProtocolEnvelope('ack-status-append', {
|
|
1089
|
+
post_id: '00000000-0000-4000-8000-000000000310',
|
|
1090
|
+
to: [acknowledgedRecipient.id, claimingRecipient.id],
|
|
1091
|
+
message: 'START NOW acknowledgement status fixture',
|
|
1092
|
+
}));
|
|
1093
|
+
expectStatus(append, 201, 'Acknowledgement-status fixture append');
|
|
1094
|
+
const entry = decodeAppendLogResultEnvelope(append.body).payload.entry;
|
|
1095
|
+
const beforeMissing = await environment.admin.observeAuthorityState();
|
|
1096
|
+
const missingResponse = await environment.operations.ackStatus(credentialA, cube, createProtocolEnvelope('ack-status-missing', { entry_id: entry.id }));
|
|
1097
|
+
expectStatus(missingResponse, 200, 'Missing acknowledgement status');
|
|
1098
|
+
const missing = decodeAckStatusResultEnvelope(missingResponse.body).payload;
|
|
1099
|
+
invariant(missing.visibility === 'direct' &&
|
|
1100
|
+
missing.recipients.length === 2 &&
|
|
1101
|
+
missing.recipients.every((recipient) => recipient.acknowledged_at === null) &&
|
|
1102
|
+
missing.claims.length === 0, 'Missing acknowledgement was not represented as nullable per-recipient state.');
|
|
1103
|
+
assertStateDelta(beforeMissing, await environment.admin.observeAuthorityState(), {}, 'Missing acknowledgement status query');
|
|
1104
|
+
expectStatus(await environment.operations.ack(acknowledgedCredential, cube, createProtocolEnvelope('ack-status-ack', { entry_id: entry.id, kind: 'ack' })), 204, 'Acknowledgement-status acknowledgement');
|
|
1105
|
+
expectStatus(await environment.operations.ack(claimingCredential, cube, createProtocolEnvelope('ack-status-claim', { entry_id: entry.id, kind: 'claim' })), 204, 'Acknowledgement-status claim');
|
|
1106
|
+
const beforeDistinct = await environment.admin.observeAuthorityState();
|
|
1107
|
+
const distinctResponse = await environment.operations.ackStatus(credentialA, cube, createProtocolEnvelope('ack-status-distinct', { entry_id: entry.id }));
|
|
1108
|
+
expectStatus(distinctResponse, 200, 'Distinct acknowledgement and claim status');
|
|
1109
|
+
const distinct = decodeAckStatusResultEnvelope(distinctResponse.body).payload;
|
|
1110
|
+
const acknowledged = distinct.recipients.filter((recipient) => recipient.acknowledged_at !== null);
|
|
1111
|
+
invariant(acknowledged.length === 1 &&
|
|
1112
|
+
acknowledged[0].drone_id === acknowledgedRecipient.id &&
|
|
1113
|
+
distinct.claims.length === 1 &&
|
|
1114
|
+
distinct.claims[0].drone_id === claimingRecipient.id &&
|
|
1115
|
+
distinct.recipients.find((recipient) => recipient.drone_id === claimingRecipient.id)?.acknowledged_at === null, 'Acknowledgement status conflated acknowledgement and claim records.');
|
|
1116
|
+
assertStateDelta(beforeDistinct, await environment.admin.observeAuthorityState(), {}, 'Distinct acknowledgement and claim status query');
|
|
1117
|
+
const unreadResponse = await environment.operations.read(credentialA, cube, createProtocolEnvelope('ack-status-unread', { cursor: null, limit: 10 }));
|
|
1118
|
+
expectStatus(unreadResponse, 200, 'Post-query unread read');
|
|
1119
|
+
const unread = decodeReadLogResultEnvelope(unreadResponse.body).payload;
|
|
1120
|
+
invariant(unread.entries.length === 1 && unread.entries[0].id === entry.id, 'Acknowledgement-status query advanced unread delivery state.');
|
|
1121
|
+
const beforeUnknown = await environment.admin.observeAuthorityState();
|
|
1122
|
+
expectError(await environment.operations.ackStatus(credentialA, cube, createProtocolEnvelope('ack-status-unknown', {
|
|
1123
|
+
entry_id: '00000000-0000-4000-8000-000000000311',
|
|
1124
|
+
})), 404, ErrorCode.NOT_FOUND, 'Unknown acknowledgement-status entry');
|
|
1125
|
+
assertStateDelta(beforeUnknown, await environment.admin.observeAuthorityState(), {}, 'Unknown acknowledgement status query');
|
|
1126
|
+
return {
|
|
1127
|
+
missing_acknowledgement: null,
|
|
1128
|
+
acknowledgements: 1,
|
|
1129
|
+
claims: 1,
|
|
1130
|
+
distinct: true,
|
|
1131
|
+
unread_entry_available: true,
|
|
1132
|
+
unknown_entry_code: ErrorCode.NOT_FOUND,
|
|
1133
|
+
};
|
|
1134
|
+
});
|
|
982
1135
|
await record('claims.durable-noncursor', async () => {
|
|
983
1136
|
invariant(entries[1] && liveCursor, 'Log fixtures did not produce claim state.');
|
|
984
1137
|
const claim = await environment.operations.ack(credentialA, cubeA, createProtocolEnvelope('claim-entry2', { entry_id: entries[1].id, kind: 'claim' }));
|
|
@@ -1217,8 +1370,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
1217
1370
|
expectError(await environment.operations.append(credentialA, cubeA, createProtocolEnvelope('evict-direct-target', {
|
|
1218
1371
|
message: 'must-not-fan-out',
|
|
1219
1372
|
post_id: '00000000-0000-4000-8000-000000000310',
|
|
1220
|
-
|
|
1221
|
-
recipientDroneIds: [evictedDrone.id],
|
|
1373
|
+
to: [evictedDrone.id],
|
|
1222
1374
|
})), 404, ErrorCode.NOT_FOUND, 'Evicted direct recipient');
|
|
1223
1375
|
expectError(await environment.operations.read(evictedCredential, cubeA, createProtocolEnvelope('evict-probe-after', { cursor: null, limit: 1 })), PROTOCOL_HTTP_CONTRACT.drone_evicted_status, ErrorCode.DRONE_EVICTED, 'Evicted seat probe');
|
|
1224
1376
|
return {
|
|
@@ -1270,12 +1422,6 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
1270
1422
|
isHumanSeat: true,
|
|
1271
1423
|
name: 'Human Seat',
|
|
1272
1424
|
});
|
|
1273
|
-
const referencedRole = await environment.admin.createRole(roleContractCube, {
|
|
1274
|
-
roleClass: 'worker',
|
|
1275
|
-
isHumanSeat: false,
|
|
1276
|
-
name: 'Routed Reviewer',
|
|
1277
|
-
});
|
|
1278
|
-
await environment.admin.referenceRoleFromTaxonomy(roleContractCube, referencedRole);
|
|
1279
1425
|
const activeRole = await environment.admin.createRole(roleContractCube, {
|
|
1280
1426
|
roleClass: 'worker',
|
|
1281
1427
|
isHumanSeat: false,
|
|
@@ -1286,7 +1432,6 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
1286
1432
|
[defaultRole, ErrorCode.DEFAULT_ROLE_REQUIRED, 'default role'],
|
|
1287
1433
|
[mandatoryRole, ErrorCode.ROLE_REQUIRED, 'mandatory role'],
|
|
1288
1434
|
[humanRole, ErrorCode.ROLE_REQUIRED, 'human-seat role'],
|
|
1289
|
-
[referencedRole, ErrorCode.ROLE_REFERENCED, 'taxonomy-referenced role'],
|
|
1290
1435
|
[activeRole, ErrorCode.ROLE_IN_USE, 'active-drone role'],
|
|
1291
1436
|
];
|
|
1292
1437
|
for (const [index, [role, code, label]] of refusals.entries()) {
|
|
@@ -1324,6 +1469,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
1324
1469
|
const evictedSession = await environment.admin.issueManagedDroneSession(evictedDrone);
|
|
1325
1470
|
const attributed = await environment.operations.append(evictedSession, roleContractCube, createProtocolEnvelope('role-delete-attribution', {
|
|
1326
1471
|
post_id: '00000000-0000-4000-8000-000000000311',
|
|
1472
|
+
to: 'broadcast',
|
|
1327
1473
|
message: 'attribution survives',
|
|
1328
1474
|
}));
|
|
1329
1475
|
expectStatus(attributed, 201, 'Pre-delete attributed log');
|
|
@@ -1341,7 +1487,6 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
1341
1487
|
ErrorCode.ROLE_IN_USE,
|
|
1342
1488
|
ErrorCode.DEFAULT_ROLE_REQUIRED,
|
|
1343
1489
|
ErrorCode.ROLE_REQUIRED,
|
|
1344
|
-
ErrorCode.ROLE_REFERENCED,
|
|
1345
1490
|
],
|
|
1346
1491
|
in_use_message_actionable: true,
|
|
1347
1492
|
evicted_drone_retargeted: true,
|
|
@@ -1746,6 +1891,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
1746
1891
|
const droneCredential = await environment.admin.issueManagedDroneSession(drone);
|
|
1747
1892
|
const append = await environment.operations.append(creator.credential, cube, createProtocolEnvelope('delete-log', {
|
|
1748
1893
|
post_id: '00000000-0000-4000-8000-000000000312',
|
|
1894
|
+
to: 'broadcast',
|
|
1749
1895
|
message: 'deleted with cube',
|
|
1750
1896
|
}));
|
|
1751
1897
|
expectStatus(append, 201, 'Deletion fixture log');
|