Name the skill for what triggers it. Cite Wikipedia on capability-based security and ambient authority, and point newcomers to awesome-ocap. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
3.8 KiB
name, description
| name | description |
|---|---|
| no-ambient-authority | Use when writing or reviewing code whose functions touch I/O, clocks, random number generators, process.env, fetch, or filesystem; when someone says "ambient authority", "wash your mouth out", or "that function shouldn't reach for that"; when debating dependency injection or default-arg seams; when asked what OCap discipline is. Source: the Agoric wiki's OCap Discipline page. |
OCap Discipline
Agoric's OCap Discipline wiki page, condensed to working rules.
the background, in three lines
Object-capability security
(capability-based security)
= memory safety + encapsulation ("no
reference to an object except: create it, be given it at creation, or
receive it in a message") combined with primitive effects only via
references — all world-touching primitives are embodied by objects,
and anything globally accessible is immutable data. No open(filename)
in the global namespace: converting a string to file access is like
casting an integer to a pointer; that's
ambient authority.
JavaScript doesn't enforce this; the discipline is a convention
(layerable via SES).
New to object capabilities? Start with awesome-ocap, a curated list of capability-based languages, systems, papers, and talks.
the working rules (from the wiki)
- Exported functions depend only on their arguments. I/O, clocks,
RNGs,
process.env, network — injected as parameters, never imported inside the function body.- transitional seam: a default argument the caller may override
- modules must not export powerful objects (nothing closing
over
fsorprocess.env) - avoid static mutable state
- Program scripts are the exception: they start
#!/usr/bin/env node(and +x), are free to import all the authority they need, then delegate it downward. - Test scripts are named
test-*.js; tests export nothing.
how this shows up in review
crypto.getRandomValues()called inside an exported function → ambient RNG authority: untestable, unreplayable, uncomposable. Fix: the function takes the random bytes (or anEntropyobject) as a parameter; the caller at the edge is who holds the ambient right.new Date()inside logic → ambient clock. Same treatment: parameter, default to a live-clock implementation.fetch/fs/envreferenced directly inside a helper's body → helpers become untestable without monkey-patching; inject a narrower interface (the caller passes the one URL's worth of fetch, not the whole world).- A module's default export closing over bindings/config → a powerful object export. Split: pure logic (argument-only) + a thin program-script-ish edge that wires authority in.
canonical fixes
// ambient: untestable
export function mintKey(): string {
return b32(crypto.getRandomValues(new Uint8Array(16)));
}
// disciplined: entropy in, key out (caller holds the RNG authority)
export const mintKey = (entropy: Entropy): string => b32(entropy(16));
references
- OCap Discipline — Agoric wiki (Miller, Robust Composition PhD thesis, 2006, is the deep source)
- Ambient authority — Wikipedia
- Capability-based security — Wikipedia
- awesome-ocap: Awesome Object Capabilities and Capability-based Security
- in this workspace:
capsite/docs/webkeys.md(URL-borne bearers), Agoric's eslit-based enforcement notes for contracts