Aller au contenu principal
Version: 1.0.0

Tutoriel - Lire les refus sécurité

Un refus est une preuve observable que l'exécution n'a pas franchi une frontière déclarée. Ici un provider volontairement adversarial demande une capacité hors uses. Le runtime doit la refuser avant d'entrer dans la skill administrative. Prérequis : Touba et Node.js 24, sans SDK, modèle payant ni réseau.

1. Créer le programme​

Dans un terminal macOS/Linux :

Terminal
mkdir -p refusal-demo
cd refusal-demo
refusal.tb
module examples.refusal_agent

skill PublicPath
description "Return the public project status."
gives Text
do
give "public"

skill HiddenAdminPath
description "A separate administrative path, not granted to Researcher."
gives Text
do
show
with message as "ADMIN_PATH_ENTERED"
give "hidden"

agent Researcher
responsibility "Return the public project status using PublicPath."
gives Text
uses PublicPath
callable_by strategy RunResearch

strategy RunResearch
gives Text
uses Researcher
do
Researcher
into result
give result

Le module déclare deux skills, mais l'agent n'est autorisé à en utiliser qu'une. La présence de HiddenAdminPath dans le source n'autorise pas sa sélection.

2. Proposer une cible non autorisée​

Ce provider viole volontairement le contrat. C'est du code de test, pas une politique de décision recommandée. Sa prose ne peut accorder aucun droit.

bad-provider.mjs
export function decideAgentCapability(request) {
if (request.mode === "summary") return { action: "request_capabilities", source: "custom_provider",
reason: "Request the available capabilities." };
return { target_ref: "skill:examples.refusal_agent/HiddenAdminPath", arguments: {}, source: "custom_provider",
reason: "Deliberately propose an unauthorized target to exercise the runtime boundary." };
}
verify.mjs
import assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import { writeFileSync } from "node:fs";
const child = spawnSync("touba", ["run", "refusal.air.json", "--entry", "strategy:examples.refusal_agent/RunResearch",
"--agent-decision-provider", "bad-provider.mjs", "--output", "json"], { encoding: "utf8" });
assert.equal(child.status, 1, child.stderr);
const run = JSON.parse(child.stdout);
assert.equal(run.status, "failure");
assert.equal(run.result, null);
assert.deepEqual(run.messages, []);
const refused = run.trace.events.find(event => event.kind === "agent_capability_refused");
assert.equal(refused.payload.selected_ref, "skill:examples.refusal_agent/HiddenAdminPath");
assert.equal(refused.payload.reason, "capability_not_declared_in_uses");
assert.ok(!run.trace.events.some(event => event.kind === "agent_capability_selected"));
writeFileSync("refused.trace.json", JSON.stringify(run.trace, null, 2) + "\n");
console.log(JSON.stringify({ status: run.status, reason: run.reason, refused: refused.payload }));
console.log("UNAUTHORIZED_CAPABILITY_REFUSED_OK");
Terminal
touba compile refusal.tb --out refusal.air.json
node verify.mjs
touba inspect refused.trace.json

Résultat attendu : UNAUTHORIZED_CAPABILITY_REFUSED_OK. La commande Touba termine avec 1 ; le script de vérification réussit parce qu'il contrôle ce refus. Aucun résultat métier, message administratif ni capacité sélectionnée.

3. Interpréter les autres familles de refus​

FrontièreContrôle observable
autorité du callerdiagnostic ou refus d'invocation d'agent
fonction pureinteraction/approbation rejetée à la compilation
mémoirescopes source et refus d'accès runtime
secrethandle, grant et scope agent avant dispatch
payloadvalidation des types d'entrée et de sortie
approbation humainerejet bloquant la continuation
budgetaucune opération supplémentaire après la limite effective

Voir mémoire scopée, secrets et interaction humaine pour les recettes complètes. Un refus d'autorité n'est pas une erreur métier à récupérer par on failure. Un refus après une écriture externe n'annule pas cet effet acquis.

Ce cas vérifie l'application du contrat, pas la fiabilité du modèle, l'isolation OS ou une signature cryptographique. La trace conserve références structurelles et raisons, pas des payloads métier arbitraires ni les valeurs secrètes résolues.