Access control
Deny-by-default tool grants. Module: mechaharness.core.access.
Stability: evolving.
Surface
Item |
Value |
|---|---|
Module |
|
Event |
|
Stability |
evolving |
Grants
Grant is a class hierarchy, not an enum. Intermediate classes set
namespace; leaves set name. The wire form is namespace:name. Unknown
namespaced keys round-trip; bare names (fs.write) are rejected.
Built-in CoreGrant leaves (FsRead, FsWrite, NetHttp, MediaImage,
MediaVideo, MediaAudio) are conveniences. Hosts add types without editing
this package:
from mechaharness.core.access import Grant
class Widget(Grant):
namespace = "acme"
name = "widget"
assert Widget.key() == "acme:widget"
Grant.parse("core:fs.write") returns the registered class. Unregistered keys
still store on AccessPolicy.grants; parse raises KeyError for those.
Policy and checks
AccessPolicy is a grant list. A tool may run only when every grant it
declares is held (set(required) <= set(granted)). Tools that declare no
grants always pass.
CompoundPolicy unions several AccessPolicy layers into one grant set
(first-seen order; overlaps are idempotent). There is no deny grant — only
allow-list membership. Use it to compose reusable profiles (read-only,
media-allowed, …) without rewriting lists. It is unrelated to
JudgementPolicy (signals → verdict).
InMemoryAccessControl holds the flattened list, records each check, and emits
core:access_check when agent_id and run_id are set.
Bind grants through Config:
from mechaharness.core.access import AccessPolicy, CompoundPolicy, FsRead, FsWrite, MediaImage
from mechaharness.di import MechaHarnessConfig
class AppConfig(MechaHarnessConfig):
def get_access_policy(self):
read_only = AccessPolicy(grants=[FsRead])
media = AccessPolicy(grants=[MediaImage])
return CompoundPolicy.of(read_only, media)
# Or simply:
# def get_grants(self):
# return [FsWrite]
get_access_control() uses get_access_policy() (default: AccessPolicy from
get_grants()). Or pass
access=InMemoryAccessControl(policy=CompoundPolicy.of(...), event_log=log)
into AbstractHarness. Denied tools return an error ToolResult and are not
priced.
Tools
Tool / ToolRegistry.tool() accept grants= (classes or namespace:name
strings) and ability= (Ability, default simple). Demo echo / add
tools declare none.