Workspace/Mini projects
Loading progress
All mini projects
MODULE 22 · 6 HOUR BUILD

A capability broker with an approval inbox

Build a local action broker for a synthetic report assistant. Its artifact is a policy decision journal and a review screen or command that shows the exact action before approval.

Build evidence Record your actual checks, results, and limitations.

Build it in stages

  1. Document trusted controller inputs and untrusted model proposals separately.
  2. Extend the seed with actor, resource version, expiry, and exact argument validation.
  3. Add a review command that records an approval for one displayed canonical action.
  4. Simulate indirect prompt injection through report text and recipient substitution.
  5. Test cross-tenant access, stale versions, expired grants, changed payloads, and revoked approvals.
  6. Write a boundary document identifying which protections are simulated and which require a real identity service and execution sandbox.

Your acceptance criteria

Use these as your project review. Record commands, outputs, and failure cases in your repository.

  • No action outside an exact active grant is executed by the fake executor.
  • Every changed consequential payload requires a matching new approval.
  • At least six adversarial fixtures preserve tenant and resource boundaries.
  • The journal contains decisions and hashes but no credential values.

A working starting point

The seed runs as supplied. Extend it to satisfy the full brief. It is a teaching starting point, not a finished portfolio submission.

main.py
python
import hashlib
import json
from dataclasses import dataclass, field

def action_hash(action):
    raw = json.dumps(action, sort_keys=True, separators=(",", ":"))
    return hashlib.sha256(raw.encode()).hexdigest()

@dataclass
class Broker:
    grants: set
    approved: set = field(default_factory=set)
    journal: list = field(default_factory=list)

    def review(self, action):
        return json.dumps(action, sort_keys=True)

    def approve_for_demo(self, action):
        self.approved.add(action_hash(action))

    def decide(self, action):
        scope = (action["tenant"], action["tool"], action["resource"])
        if scope not in self.grants:
            decision = "deny"
        elif action["tool"] == "send" and action_hash(action) not in self.approved:
            decision = "approval_required"
        else:
            decision = "allow"
        self.journal.append((decision, action_hash(action)[:10]))
        return decision

def main():
    broker = Broker({("blue", "send", "report-7")})
    action = {"tenant": "blue", "tool": "send", "resource": "report-7",
              "args": {"to": "review@example.test", "revision": 8}}
    print("review:", broker.review(action))
    print("before:", broker.decide(action))
    broker.approve_for_demo(action)
    print("after:", broker.decide(action))
    changed = dict(action, args={"to": "other@example.test", "revision": 8})
    print("changed:", broker.decide(changed))
    print("cross tenant:", broker.decide(dict(action, tenant="red")))
    print("journal entries:", len(broker.journal))

if __name__ == "__main__":
    main()

Push it further

Place a real broker in front of a disposable sandbox and demonstrate filesystem and network enforcement using harmless boundary tests.