Guide
Give a check the inputs it needs
Some questions need more than source code: a finite set of concurrent requests, a view of related implementations, or seeded database rows. These examples supply those inputs. The safety guide explains which tool to choose and what its result means.
Connect your agent, open the WebMCP workbench, and ask it to run these requests using the linked files.
Check retries, receipts, and concurrent requests
api_protocol_check explores compiled handlers within a declared finite case.
It can check that an acknowledged withdrawal has a matching durable receipt, including
schedules with uncertain commits. It does not contact a production database.
Download the withdrawal program and its complete case. These are the fixed twin and case from the repository’s transaction-receipt evaluation. Read each file in full, then call:
api_protocol_check({
"sources": [{"fileName": "withdrawal.bosatsu", "source": SOURCE_TEXT}],
"case": PARSED_CASE_JSON
})
Inspect protocol and allHold. A completed search establishes only
this finite case; a holds result still has proven: false. Exhausted bounds,
unsupported operations, and missing required witnesses are inconclusive.
All required case fields
The version is protocol-case-1.0. Every field below is required, even when
its value is an empty array or object. Unknown fields and duplicate JSON keys are errors.
- schemaVersion, name
- The exact version string and a case name.
- assumptions
- Exactly the six strings in the linked case, once each. They include serializable atomic transactions, no unmodeled writers, and preauthenticated principals.
- initialRows
- Table names mapped to row-key/value objects. Values follow the checked row types.
- initialize
- Ordered seed calls with
call, integertime, andoutcome(committedorunknown-committed). These seed a state; their history is not explored. - requests
- Objects with
instance,delivery, andcall. Each instance/delivery pair is unique. A call names a qualifiedbindingandargumentsby parameter name; omit Db, which the checker supplies. - times
- A nonempty, strictly increasing array of integer clock values.
- externalResults
- External binding names mapped to nonempty arrays of typed possible results. The closed model supports article fetch and OpenRouter model calls; unsupported externals are refused.
- invariants
- Named compiled IO[Bool] observations with argument selectors and a
whencondition. Predicates may read model databases, not mutate them. - traceInvariants
- Named structural assertions, such as
return-receipt,immutable-rows, andatomic-writes. At least one invariant across the two invariant arrays is required. - witnesses
- Named conditions the search must reach, such as a returned request or nonempty receipt table. An unobserved requirement does not silently pass.
- bounds
- Positive integers
maxStates,maxDepth,maxOperations; nonnegativemaxFaultsandmaxCrashes.
The full protocol specification defines every selector, trace assertion, witness, and assumption. Read it before constructing a new case.
Keep the requirement separate from the implementation. Changing a receipt assertion to accept the receipt your broken handler happens to return does not repair that handler.
Compare implementations against a question
Start with api_abstraction_map for definitions, dependencies, and layers.
Use api_organize with lens: "stack" for reading order and a map,
"conventions" for neighboring signatures, or "page" for reuse and bypasses.
The "implementations" lens adds an authored question, pinned definitions, and comparison roles.
Read the moderator example and its complete view, then call:
api_organize({
"sources": [{"fileName": "moderator-notes.bosatsu", "source": SOURCE_TEXT}],
"lens": "implementations",
"view": JSON.stringify(PARSED_VIEW_JSON)
})
Check ok before reading comparison. The engine validates the
referenced definitions and regenerates references, signatures, effects, and source locations.
Your group labels and comparison question remain your interpretation; they do not prove organization quality or access safety.
The implementation-view-1 format
- schemaVersion
- Exactly
implementation-view-1. - question
- Nonempty text, at most 500 characters.
- pins
- A nonempty array of distinct
Package/Name::bindingidentities from supplied user packages. - groups
- An array, possibly empty. Each group has unique
id,label,members(binding identities), and optionalparent(group id). A definition may belong directly to one group; parents must exist and cannot cycle. - roles
- A nonempty array of objects with unique
id,label, andreferences(binding identities).$effectsis reserved. - order
- Optional manual layout order, using
node:Package/Name::bindingandgroup:id. Omit it to let dependencies determine the order.
Unknown fields, duplicate identities within a list, and nonexistent binding references are refused.
Use exact identities from the map instead of guessing package names. focus applies to the stack lens; implementation views use pins.
Seed the key the handler will actually read
api_why accepts rows as table names mapped to key/value objects.
For owner_key(principal, local_key), derive the key using that same Bosatsu function.
This helper is for computing a test-world key. In the service under analysis, keep
owner_key directly at the database operation: the access checker currently
cannot follow its proof through a helper function.
A row under the plain local key is a different row.
Read the key helper as SOURCE_TEXT and evaluate it:
api_why({
"sources": [{"fileName": "owner-key.bosatsu", "source": SOURCE_TEXT}],
"binding": "Yichus/Examples/OwnerKey::key_for",
"inputs": {"p": {"user_id": "u1", "roles": []}, "local_key": "c1"},
"observe": false
})
The helper returns IO[String] because the current Why evaluator requires IO for entry points taking a Principal. The key calculation itself is pure.
The returned String is 2:u1c1. Use that value as the JSON row key;
for different inputs, evaluate the same helper instead of reimplementing the encoding.
Read the Access package source for its definition.
Direct handler evaluation uses your supplied identity and seeded world; it does not authenticate an HTTP caller.
Where this fits
What this is about: Safety and Permissions