@@ -202,6 +202,39 @@ pub export fn boj_cartridge_version() [*:0]const u8 {
202202 return "0.1.0" ;
203203}
204204
205+ // ═══════════════════════════════════════════════════════════════════════
206+ // ADR-0006 dispatch (boj_cartridge_invoke, 5th standard symbol)
207+ // ═══════════════════════════════════════════════════════════════════════
208+
209+ const shim = @import ("cartridge_shim" );
210+
211+ /// Dispatch the cartridge.json MCP tools. Grade D Alpha — each arm
212+ /// returns a stub JSON body shaped to the tool's intended response.
213+ export fn boj_cartridge_invoke (
214+ tool_name : [* c ]const u8 ,
215+ json_args : [* c ]const u8 ,
216+ out_buf : [* c ]u8 ,
217+ in_out_len : [* c ]usize ,
218+ ) callconv (.c ) i32 {
219+ _ = json_args ;
220+ if (shim .invokeArgsNull (tool_name , out_buf , in_out_len )) return shim .RC_BAD_ARGS ;
221+
222+ const body : []const u8 = if (shim .toolIs (tool_name , "secrets_unseal" ))
223+ "{\" result\" :{\" status\" :\" stub\" }}"
224+ else if (shim .toolIs (tool_name , "secrets_authenticate" ))
225+ "{\" result\" :{\" status\" :\" stub\" }}"
226+ else if (shim .toolIs (tool_name , "secrets_get" ))
227+ "{\" result\" :{\" status\" :\" stub\" }}"
228+ else if (shim .toolIs (tool_name , "secrets_set" ))
229+ "{\" result\" :{\" status\" :\" stub\" }}"
230+ else if (shim .toolIs (tool_name , "secrets_seal" ))
231+ "{\" result\" :{\" status\" :\" stub\" }}"
232+ else
233+ return shim .RC_UNKNOWN_TOOL ;
234+
235+ return shim .writeResult (out_buf , in_out_len , body );
236+ }
237+
205238// ═══════════════════════════════════════════════════════════════════════
206239// Tests
207240// ═══════════════════════════════════════════════════════════════════════
@@ -268,3 +301,39 @@ test "state transition validation" {
268301 try std .testing .expectEqual (@as (c_int , 0 ), sec_can_transition (0 , 3 )); // sealed -> accessing
269302 try std .testing .expectEqual (@as (c_int , 0 ), sec_can_transition (3 , 0 )); // accessing -> sealed
270303}
304+
305+ // ═══════════════════════════════════════════════════════════════════════
306+ // ADR-0006 invoke dispatch tests
307+ // ═══════════════════════════════════════════════════════════════════════
308+
309+ test "invoke: each declared tool succeeds" {
310+ var buf : [256 ]u8 = undefined ;
311+ const tools = [_ ][]const u8 {
312+ "secrets_unseal" ,
313+ "secrets_authenticate" ,
314+ "secrets_get" ,
315+ "secrets_set" ,
316+ "secrets_seal" ,
317+ };
318+ for (tools ) | t | {
319+ var len : usize = buf .len ;
320+ const rc = boj_cartridge_invoke (t .ptr , "{}" , & buf , & len );
321+ try std .testing .expectEqual (@as (i32 , 0 ), rc );
322+ try std .testing .expect (std .mem .indexOf (u8 , buf [0.. len ], "result" ) != null );
323+ }
324+ }
325+
326+ test "invoke: unknown tool returns -1" {
327+ var buf : [64 ]u8 = undefined ;
328+ var len : usize = buf .len ;
329+ const rc = boj_cartridge_invoke ("nope" , "{}" , & buf , & len );
330+ try std .testing .expectEqual (@as (i32 , -1 ), rc );
331+ }
332+
333+ test "invoke: buffer too small returns -3" {
334+ var buf : [4 ]u8 = undefined ;
335+ var len : usize = buf .len ;
336+ const rc = boj_cartridge_invoke ("secrets_unseal" , "{}" , & buf , & len );
337+ try std .testing .expectEqual (@as (i32 , -3 ), rc );
338+ try std .testing .expect (len > 4 );
339+ }
0 commit comments