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>
82 lines
3.8 KiB
Markdown
82 lines
3.8 KiB
Markdown
---
|
|
name: no-ambient-authority
|
|
description: >-
|
|
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](https://github.com/Agoric/agoric-sdk/wiki/OCap-Discipline),
|
|
condensed to working rules.
|
|
|
|
## the background, in three lines
|
|
|
|
Object-capability security
|
|
([capability-based security](https://en.wikipedia.org/wiki/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](https://en.wikipedia.org/wiki/Ambient_authority).
|
|
JavaScript doesn't enforce this; the discipline is a convention
|
|
(layerable via SES).
|
|
|
|
New to object capabilities? Start with
|
|
[awesome-ocap](https://github.com/dckc/awesome-ocap), a curated list of
|
|
capability-based languages, systems, papers, and talks.
|
|
|
|
## the working rules (from the wiki)
|
|
|
|
1. **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 `fs` or `process.env`)
|
|
- avoid static mutable state
|
|
2. **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.
|
|
3. **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 an `Entropy` object)
|
|
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` / `env` referenced 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
|
|
|
|
```ts
|
|
// 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](https://github.com/Agoric/agoric-sdk/wiki/OCap-Discipline)
|
|
(Miller, *Robust Composition* PhD thesis, 2006, is the deep source)
|
|
- [Ambient authority — Wikipedia](https://en.wikipedia.org/wiki/Ambient_authority)
|
|
- [Capability-based security — Wikipedia](https://en.wikipedia.org/wiki/Capability-based_security)
|
|
- [awesome-ocap: Awesome Object Capabilities and Capability-based Security](https://github.com/dckc/awesome-ocap)
|
|
- in this workspace: `capsite/docs/webkeys.md` (URL-borne bearers),
|
|
Agoric's eslit-based enforcement notes for contracts |