Members
members restricts the names appearing inside a file, in one of two positions: the names
written in a declaration, and the names called. It is how a policy states a vocabulary — a
set of names a stereotype is allowed to use — where the constraint is not about which modules
are reached at all.
"*.repository.ts": members: - message: >- A repository port method named "{name}" is a query in disguise. A port loads and saves an aggregate by identity; anything keyed on another column is a read model, and belongs in queries/. subject: members declares: [type, interface] in: "*RepositoryShape" match: "find*" matchNot: [findOneById, findManyByIds]| Field | Meaning |
|---|---|
subject |
members or calls |
declares |
for members, which declaration kinds: type, interface, class |
in |
for members, globs against the declaration’s own name |
match |
names the rule is about. Omit to mean every name in that position |
matchNot |
names carved back out of match |
allow |
names permitted; anything matched and not allowed is the violation |
message |
why. {name} is substituted with the offending name |
probe |
{ source, name } — a snippet the rule must report name out of |
match/matchNot narrow what the rule is about; allow says which of those are fine.
Either side can carry the exemption — the find* example above uses matchNot, and a hook
allowlist below uses allow — and which reads better depends on whether the exceptions are
the interesting part.
members
Section titled “members”The names written in a declaration — a type alias, an interface or a class body — with in
selecting the declaration by name and declares by kind:
type UserRepositoryShape = { readonly findOneById: (id: UserId) => Effect<UserRoot>; readonly findOneByEmail: (email: string) => Effect<UserRoot>; // ← reported};A computed key is skipped: it is not a name a vocabulary rule can speak about. Neither is a
class’s constructor or a private #name.
declares is what separates a rule about a port from a rule about the adapter that
implements it. ["type", "interface"] is the port’s vocabulary; ["class"] reaches the
class body; omitting it speaks to every declaration in the file.
Called identifiers and called members — useState(0) and React.useEffect(fn) both
produce a site named for the callee:
"*.view.tsx": members: - message: "`{name}` puts state in the View. It belongs in the ViewModel." subject: calls match: "use[A-Z]*" allow: [useAtomValue, useAtomSet, useAtomSuspense, useId, useCallback]The use[A-Z]* pattern is the reason character classes
exist in the glob language: it means a hook, without also matching user or useful.
Which declarations are read
Section titled “Which declarations are read”members reads the members written in a named declaration, under that declaration’s
name — a type alias, an interface, or a class, and inside an alias, through
intersections, unions and parentheses:
type Base = { save(): void };type Port = Base & { findOneById(): void }; // Port.findOneById — and Base.save, under Baseinterface Other extends Base { findMany(): void;} // Other.findManyclass Live implements Port { findOneById() {} // Live.findOneById, declared as `class`}A reference is not followed. Base’s members are declared where Base is and are reported
there under its own name; following the reference would report every member twice, under
two names. So an in pattern must name the declaration where the member is actually
written.
Not read: an anonymous class (export default class {}) or a class expression, a
constructor, a private #name, index, call and construct signatures, mapped types, and
computed keys.
Proving the rule reads your shape
Section titled “Proving the rule reads your shape”A rule about a shape the extractor does not read would pass its generated probe while reporting nothing.
An authored probe closes that: the snippet is parsed at load, and the rule must report
name out of what the parser read, or the policy refuses to load.
probe: source: "export type TodosRepositoryShape = { findOneByEmail(): void };" name: findOneByEmailWrite it in the shape your real ports take. See Probes.
Several rules on one node
Section titled “Several rules on one node”members is an array, and each entry is compiled to its own rule with its own probe. A
node that constrains both what it declares and what it calls states both, and a violation
names which one fired.