borgmcp-shared 0.14.0 → 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 +9 -2
- package/dist/conformance/adapter.d.ts.map +1 -1
- package/dist/conformance/adapter.js +128 -43
- package/dist/conformance/adapter.js.map +1 -1
- package/dist/conformance/index.d.ts +25 -3
- package/dist/conformance/index.d.ts.map +1 -1
- package/dist/conformance/index.js +73 -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 +10 -0
- package/dist/protocol/coordination.d.ts.map +1 -1
- package/dist/protocol/coordination.js +20 -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 +7 -79
- package/dist/templates.js.map +1 -1
- package/docs/compatibility.md +9 -0
- package/docs/release-records.json +14 -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 +232 -52
- package/src/conformance/index.ts +88 -22
- package/src/protocol/contract.ts +15 -21
- package/src/protocol/coordination.ts +36 -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 +7 -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.
|
|
@@ -62,6 +62,7 @@ export interface ConformanceAuthorityState {
|
|
|
62
62
|
enrollment_claims: number;
|
|
63
63
|
activity_acknowledgements: number;
|
|
64
64
|
activity_claims: number;
|
|
65
|
+
activity_log_entries: number;
|
|
65
66
|
cubes: number;
|
|
66
67
|
roles: number;
|
|
67
68
|
grants: number;
|
|
@@ -132,8 +133,7 @@ export interface ConformanceAdmin {
|
|
|
132
133
|
readonly isDefault?: boolean;
|
|
133
134
|
readonly isMandatory?: boolean;
|
|
134
135
|
}): Promise<ConformanceRole>;
|
|
135
|
-
|
|
136
|
-
configureMessageClassRouting(cube: ConformanceCube, className: string, recipientDroneIds: readonly string[]): Promise<void>;
|
|
136
|
+
replaceLogEntryId(cube: ConformanceCube, currentId: string, replacementId: string): Promise<void>;
|
|
137
137
|
createDrone(principal: ConformancePrincipal, cube: ConformanceCube, role: ConformanceRole): Promise<ConformanceDrone>;
|
|
138
138
|
issueManagedDroneSession(drone: ConformanceDrone): Promise<string>;
|
|
139
139
|
revokeManagedDroneSession(drone: ConformanceDrone): Promise<void>;
|
|
@@ -176,6 +176,7 @@ export interface ConformanceOperations {
|
|
|
176
176
|
append(credential: string, cube: ConformanceCube, request: unknown): Promise<ConformanceHttpResponse>;
|
|
177
177
|
appendRaw(credential: string, cube: ConformanceCube, body: string): Promise<ConformanceHttpResponse>;
|
|
178
178
|
read(credential: string, cube: ConformanceCube, request: unknown): Promise<ConformanceHttpResponse>;
|
|
179
|
+
entryQuery(credential: string, cube: ConformanceCube, request: unknown): Promise<ConformanceHttpResponse>;
|
|
179
180
|
ack(credential: string, cube: ConformanceCube, request: unknown): Promise<ConformanceHttpResponse>;
|
|
180
181
|
ackStatus(credential: string, cube: ConformanceCube, request: unknown): Promise<ConformanceHttpResponse>;
|
|
181
182
|
updateCube(credential: string, cube: ConformanceCube, request: unknown): Promise<ConformanceHttpResponse>;
|
|
@@ -224,6 +225,12 @@ export declare const ADAPTER_CONFORMANCE_FIXTURES: readonly [{
|
|
|
224
225
|
}, {
|
|
225
226
|
readonly id: "log.append-idempotency";
|
|
226
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";
|
|
227
234
|
}, {
|
|
228
235
|
readonly id: "log.read-cursor-tuple";
|
|
229
236
|
readonly area: "cursor";
|
|
@@ -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, decodeAckStatusResultEnvelope, 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,6 +11,8 @@ 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' },
|
|
@@ -668,6 +670,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
668
670
|
const entriesBeforeForeignCitation = decodeReadLogResultEnvelope((await environment.operations.read(documentCredential, documentCube, createProtocolEnvelope('document-read-before-foreign-cite', { cursor: null, limit: 100 }))).body).payload.entries.length;
|
|
669
671
|
expectSecretFreeError(await environment.operations.append(documentCredential, documentCube, createProtocolEnvelope('document-foreign-citation', {
|
|
670
672
|
post_id: '00000000-0000-4000-8000-00000000031f',
|
|
673
|
+
to: 'broadcast',
|
|
671
674
|
message: 'Foreign evidence must remain hidden.',
|
|
672
675
|
documents: [foreignDocument.id],
|
|
673
676
|
})), 404, ErrorCode.DOCUMENT_NOT_FOUND, 'Foreign document citation', [foreignDocument.title, foreignDocument.content]);
|
|
@@ -687,6 +690,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
687
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');
|
|
688
691
|
const citationResponse = await environment.operations.append(documentCredential, documentCube, createProtocolEnvelope('document-citation', {
|
|
689
692
|
post_id: '00000000-0000-4000-8000-000000000320',
|
|
693
|
+
to: 'broadcast',
|
|
690
694
|
message: 'See the document evidence.',
|
|
691
695
|
documents: [created.id, successor.id],
|
|
692
696
|
}));
|
|
@@ -695,6 +699,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
695
699
|
invariant(cited?.length === 2 && cited[0].state === 'superseded', 'Log citations did not render document metadata and state.');
|
|
696
700
|
expectError(await environment.operations.append(documentCredential, documentCube, createProtocolEnvelope('document-citation-conflict', {
|
|
697
701
|
post_id: '00000000-0000-4000-8000-000000000320',
|
|
702
|
+
to: 'broadcast',
|
|
698
703
|
message: 'See the document evidence.',
|
|
699
704
|
documents: [successor.id],
|
|
700
705
|
})), 409, ErrorCode.POST_ID_CONFLICT, 'Document citation post-id conflict');
|
|
@@ -735,15 +740,15 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
735
740
|
const entriesBeforeUnknownCitation = (await environment.operations.read(documentCredential, documentCube, createProtocolEnvelope('document-read-before-unknown-cite', { cursor: null, limit: 100 })));
|
|
736
741
|
const beforeCount = decodeReadLogResultEnvelope(entriesBeforeUnknownCitation.body).payload.entries.length;
|
|
737
742
|
expectError(await environment.operations.append(documentCredential, documentCube, createProtocolEnvelope('document-unknown-citation', {
|
|
738
|
-
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'],
|
|
739
744
|
})), 404, ErrorCode.DOCUMENT_NOT_FOUND, 'Unknown document citation');
|
|
740
745
|
const longAccepted = await environment.operations.append(documentCredential, documentCube, createProtocolEnvelope('document-advisory', {
|
|
741
|
-
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',
|
|
742
747
|
}));
|
|
743
748
|
expectStatus(longAccepted, 201, 'Advisory log append');
|
|
744
749
|
invariant(decodeAppendLogResultEnvelope(longAccepted.body).payload.advisory?.threshold_bytes === 1024, 'Configured advisory was not returned.');
|
|
745
750
|
expectError(await environment.operations.append(documentCredential, documentCube, createProtocolEnvelope('document-hard-cap', {
|
|
746
|
-
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',
|
|
747
752
|
})), 413, ErrorCode.CONTENT_TOO_LARGE, 'Hard-cap log append');
|
|
748
753
|
const citedRead = decodeReadLogResultEnvelope((await environment.operations.read(documentCredential, documentCube, createProtocolEnvelope('document-citation-read', { cursor: null, limit: 10 }))).body).payload.entries[0].documents;
|
|
749
754
|
invariant(citedRead?.[0].state === 'removed', 'Log citation did not resolve the audit-retained removed state.');
|
|
@@ -758,6 +763,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
758
763
|
const injectedMessage = "'); DROP TABLE log_entries; --\r\ndata: forged-sse-frame";
|
|
759
764
|
const injectedBody = JSON.stringify(createProtocolEnvelope('inject-b1', {
|
|
760
765
|
post_id: '00000000-0000-4000-8000-000000000301',
|
|
766
|
+
to: 'broadcast',
|
|
761
767
|
message: injectedMessage,
|
|
762
768
|
}));
|
|
763
769
|
invariant(utf8ByteLength(injectedBody) <= PROTOCOL_LIMIT_CEILINGS.max_request_bytes &&
|
|
@@ -768,6 +774,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
768
774
|
invariant(injectedEntry.message === injectedMessage, 'Adapter altered or interpreted injection-shaped log data.');
|
|
769
775
|
const sentinel = await environment.operations.append(credentialB, cubeB, createProtocolEnvelope('inject-b2', {
|
|
770
776
|
post_id: '00000000-0000-4000-8000-000000000302',
|
|
777
|
+
to: 'broadcast',
|
|
771
778
|
message: 'post-injection-sentinel',
|
|
772
779
|
}));
|
|
773
780
|
expectStatus(sentinel, 201, 'Post-injection sentinel append');
|
|
@@ -800,6 +807,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
800
807
|
await record('security.oversize-request', async () => {
|
|
801
808
|
const baseBody = JSON.stringify(createProtocolEnvelope('oversize-a1', {
|
|
802
809
|
post_id: '00000000-0000-4000-8000-000000000303',
|
|
810
|
+
to: 'broadcast',
|
|
803
811
|
message: 'must-not-persist',
|
|
804
812
|
}));
|
|
805
813
|
const oversizedBody = baseBody + ' '.repeat(Math.max(0, PROTOCOL_LIMIT_CEILINGS.max_request_bytes - utf8ByteLength(baseBody) + 1));
|
|
@@ -815,6 +823,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
815
823
|
const secretAppend = await environment.operations.append(credentialB, cubeB, createProtocolEnvelope('append-b1', {
|
|
816
824
|
post_id: '00000000-0000-4000-8000-000000000304',
|
|
817
825
|
message: 'principal-b-secret',
|
|
826
|
+
to: 'broadcast',
|
|
818
827
|
}));
|
|
819
828
|
expectStatus(secretAppend, 201, 'Principal B append');
|
|
820
829
|
const denied = await environment.operations.read(credentialA, cubeB, createProtocolEnvelope('read-cross', { cursor: null, limit: 10 }));
|
|
@@ -835,44 +844,24 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
835
844
|
});
|
|
836
845
|
const firstRecipient = await environment.admin.createDrone(principal, cube, role);
|
|
837
846
|
const secondRecipient = await environment.admin.createDrone(principal, cube, role);
|
|
838
|
-
await environment.admin.configureMessageClassRouting(cube, 'conformance-review', [firstRecipient.id]);
|
|
839
|
-
await environment.admin.configureMessageClassRouting(cube, 'conformance-security', [firstRecipient.id]);
|
|
840
847
|
const postId = '00000000-0000-4000-8000-000000000313';
|
|
841
848
|
const initialPayload = {
|
|
842
849
|
post_id: postId,
|
|
843
850
|
message: 'once',
|
|
844
|
-
|
|
845
|
-
recipientDroneIds: [firstRecipient.id],
|
|
851
|
+
to: [firstRecipient.id],
|
|
846
852
|
class: 'review',
|
|
847
|
-
to: ['Coordinator'],
|
|
848
853
|
};
|
|
849
854
|
const first = await environment.operations.append(credential, cube, createProtocolEnvelope('append-idempotency-first', initialPayload));
|
|
850
855
|
expectStatus(first, 201, 'Initial idempotent append');
|
|
851
856
|
const firstResult = decodeAppendLogResultEnvelope(first.body).payload;
|
|
852
857
|
invariant(!firstResult.deduplicated, 'Initial append was reported as deduplicated.');
|
|
853
858
|
for (const [index, vector] of APPEND_LOG_IDEMPOTENCY_CONFORMANCE.entries()) {
|
|
854
|
-
const
|
|
855
|
-
const vectorPostId = classRouting
|
|
856
|
-
? '00000000-0000-4000-8000-000000000314'
|
|
857
|
-
: postId;
|
|
858
|
-
if (classRouting) {
|
|
859
|
-
const baseline = await environment.operations.append(credential, cube, createProtocolEnvelope('append-idempotency-class-baseline', {
|
|
860
|
-
post_id: vectorPostId,
|
|
861
|
-
message: 'once',
|
|
862
|
-
class: 'conformance-review',
|
|
863
|
-
}));
|
|
864
|
-
expectStatus(baseline, 201, 'Resolved class-routing baseline');
|
|
865
|
-
}
|
|
866
|
-
const payload = classRouting ? {
|
|
867
|
-
post_id: vectorPostId,
|
|
868
|
-
message: 'once',
|
|
869
|
-
class: 'conformance-security',
|
|
870
|
-
} : {
|
|
859
|
+
const payload = {
|
|
871
860
|
...initialPayload,
|
|
872
861
|
...(vector.mutation === 'message' ? { message: 'changed' } : {}),
|
|
873
|
-
...(vector.mutation === '
|
|
874
|
-
...(vector.mutation === 'recipient_set' ? {
|
|
875
|
-
...(vector.mutation === '
|
|
862
|
+
...(vector.mutation === 'audience' ? { to: 'broadcast' } : {}),
|
|
863
|
+
...(vector.mutation === 'recipient_set' ? { to: [secondRecipient.id] } : {}),
|
|
864
|
+
...(vector.mutation === 'classification' ? { class: 'security' } : {}),
|
|
876
865
|
};
|
|
877
866
|
const response = await environment.operations.append(vector.actor === 'same' ? credential : otherCredential, cube, createProtocolEnvelope(`append-idempotency-${index}`, payload));
|
|
878
867
|
if (vector.expected === 'POST_ID_CONFLICT') {
|
|
@@ -888,8 +877,109 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
888
877
|
}
|
|
889
878
|
const read = await environment.operations.read(credential, cube, createProtocolEnvelope('append-idempotency-read', { cursor: null, limit: 10 }));
|
|
890
879
|
expectStatus(read, 200, 'Idempotent append read');
|
|
891
|
-
invariant(decodeReadLogResultEnvelope(read.body).payload.entries.length ===
|
|
892
|
-
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
|
+
};
|
|
893
983
|
});
|
|
894
984
|
const entries = [];
|
|
895
985
|
let readCursor = null;
|
|
@@ -897,6 +987,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
897
987
|
for (const [index, message] of ['alpha', 'beta', 'gamma'].entries()) {
|
|
898
988
|
const response = await environment.operations.append(credentialA, cubeA, createProtocolEnvelope(`append-a${index + 1}`, {
|
|
899
989
|
post_id: `00000000-0000-4000-8000-${String(305 + index).padStart(12, '0')}`,
|
|
990
|
+
to: 'broadcast',
|
|
900
991
|
message,
|
|
901
992
|
}));
|
|
902
993
|
expectStatus(response, 201, `Append ${message}`);
|
|
@@ -922,6 +1013,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
922
1013
|
try {
|
|
923
1014
|
const appendDelta = environment.operations.append(credentialA, cubeA, createProtocolEnvelope('append-a4', {
|
|
924
1015
|
post_id: '00000000-0000-4000-8000-000000000308',
|
|
1016
|
+
to: 'broadcast',
|
|
925
1017
|
message: 'delta',
|
|
926
1018
|
}));
|
|
927
1019
|
expectStatus(await appendDelta, 201, 'Transition append');
|
|
@@ -946,6 +1038,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
946
1038
|
await provePending(noDuplicate, 'Live stream after delta', pendingProbeMs);
|
|
947
1039
|
const epsilonResponse = await environment.operations.append(credentialA, cubeA, createProtocolEnvelope('append-a5', {
|
|
948
1040
|
post_id: '00000000-0000-4000-8000-000000000309',
|
|
1041
|
+
to: 'broadcast',
|
|
949
1042
|
message: 'epsilon',
|
|
950
1043
|
}));
|
|
951
1044
|
expectStatus(epsilonResponse, 201, 'Live append');
|
|
@@ -994,9 +1087,8 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
994
1087
|
const claimingCredential = await environment.admin.issueManagedDroneSession(claimingRecipient);
|
|
995
1088
|
const append = await environment.operations.append(credentialA, cube, createProtocolEnvelope('ack-status-append', {
|
|
996
1089
|
post_id: '00000000-0000-4000-8000-000000000310',
|
|
1090
|
+
to: [acknowledgedRecipient.id, claimingRecipient.id],
|
|
997
1091
|
message: 'START NOW acknowledgement status fixture',
|
|
998
|
-
visibility: 'direct',
|
|
999
|
-
recipientDroneIds: [acknowledgedRecipient.id, claimingRecipient.id],
|
|
1000
1092
|
}));
|
|
1001
1093
|
expectStatus(append, 201, 'Acknowledgement-status fixture append');
|
|
1002
1094
|
const entry = decodeAppendLogResultEnvelope(append.body).payload.entry;
|
|
@@ -1278,8 +1370,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
1278
1370
|
expectError(await environment.operations.append(credentialA, cubeA, createProtocolEnvelope('evict-direct-target', {
|
|
1279
1371
|
message: 'must-not-fan-out',
|
|
1280
1372
|
post_id: '00000000-0000-4000-8000-000000000310',
|
|
1281
|
-
|
|
1282
|
-
recipientDroneIds: [evictedDrone.id],
|
|
1373
|
+
to: [evictedDrone.id],
|
|
1283
1374
|
})), 404, ErrorCode.NOT_FOUND, 'Evicted direct recipient');
|
|
1284
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');
|
|
1285
1376
|
return {
|
|
@@ -1331,12 +1422,6 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
1331
1422
|
isHumanSeat: true,
|
|
1332
1423
|
name: 'Human Seat',
|
|
1333
1424
|
});
|
|
1334
|
-
const referencedRole = await environment.admin.createRole(roleContractCube, {
|
|
1335
|
-
roleClass: 'worker',
|
|
1336
|
-
isHumanSeat: false,
|
|
1337
|
-
name: 'Routed Reviewer',
|
|
1338
|
-
});
|
|
1339
|
-
await environment.admin.referenceRoleFromTaxonomy(roleContractCube, referencedRole);
|
|
1340
1425
|
const activeRole = await environment.admin.createRole(roleContractCube, {
|
|
1341
1426
|
roleClass: 'worker',
|
|
1342
1427
|
isHumanSeat: false,
|
|
@@ -1347,7 +1432,6 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
1347
1432
|
[defaultRole, ErrorCode.DEFAULT_ROLE_REQUIRED, 'default role'],
|
|
1348
1433
|
[mandatoryRole, ErrorCode.ROLE_REQUIRED, 'mandatory role'],
|
|
1349
1434
|
[humanRole, ErrorCode.ROLE_REQUIRED, 'human-seat role'],
|
|
1350
|
-
[referencedRole, ErrorCode.ROLE_REFERENCED, 'taxonomy-referenced role'],
|
|
1351
1435
|
[activeRole, ErrorCode.ROLE_IN_USE, 'active-drone role'],
|
|
1352
1436
|
];
|
|
1353
1437
|
for (const [index, [role, code, label]] of refusals.entries()) {
|
|
@@ -1385,6 +1469,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
1385
1469
|
const evictedSession = await environment.admin.issueManagedDroneSession(evictedDrone);
|
|
1386
1470
|
const attributed = await environment.operations.append(evictedSession, roleContractCube, createProtocolEnvelope('role-delete-attribution', {
|
|
1387
1471
|
post_id: '00000000-0000-4000-8000-000000000311',
|
|
1472
|
+
to: 'broadcast',
|
|
1388
1473
|
message: 'attribution survives',
|
|
1389
1474
|
}));
|
|
1390
1475
|
expectStatus(attributed, 201, 'Pre-delete attributed log');
|
|
@@ -1402,7 +1487,6 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
1402
1487
|
ErrorCode.ROLE_IN_USE,
|
|
1403
1488
|
ErrorCode.DEFAULT_ROLE_REQUIRED,
|
|
1404
1489
|
ErrorCode.ROLE_REQUIRED,
|
|
1405
|
-
ErrorCode.ROLE_REFERENCED,
|
|
1406
1490
|
],
|
|
1407
1491
|
in_use_message_actionable: true,
|
|
1408
1492
|
evicted_drone_retargeted: true,
|
|
@@ -1807,6 +1891,7 @@ export async function runAdapterConformance(environment, options = {}) {
|
|
|
1807
1891
|
const droneCredential = await environment.admin.issueManagedDroneSession(drone);
|
|
1808
1892
|
const append = await environment.operations.append(creator.credential, cube, createProtocolEnvelope('delete-log', {
|
|
1809
1893
|
post_id: '00000000-0000-4000-8000-000000000312',
|
|
1894
|
+
to: 'broadcast',
|
|
1810
1895
|
message: 'deleted with cube',
|
|
1811
1896
|
}));
|
|
1812
1897
|
expectStatus(append, 201, 'Deletion fixture log');
|