Skip to content
Back to skills

Code Law

ASecurity

Use when writing or changing code in any language. Not for prose, docs-only, or config-only changes.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 16, 2026
ai-agentsrustgoshellreactexpresstestinggitapidatabasesecurity

Works with

  • terminal
  • cli
  • api

Security analysis

A100/100

Scanned October 16, 2026

npx -y skills add alleneubank/agent-profile --skill code-law --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Code Law?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Code Law
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/alleneubank-code-law/badge)](https://www.skillsdirectory.com/skills/alleneubank-code-law)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: code-law
description: Use when writing or changing code in any language. Not for prose, docs-only, or config-only changes.
---

# Code Law

The craft law for code. `AGENTS.md` keeps the law whose violation is
unrecoverable — boundary, secrets, publish, done-claims.
This skill carries the law whose violation the harness and behavior-first
verification catch.

**A property you want held is made unwritable first, detected second.**
Before reaching for any check, shape the code so the defect cannot be written:
a type the wrong value cannot inhabit, visibility that hides the wrong call, a
module boundary, the invariant kept with the state it protects, a capability
that only the authorized scope can obtain. Correct types are the proof. They
need no checker, fixture, or mutation run to show that they hold. Choose this
even when a check would be quicker to add today.

Where construction cannot hold a property, a sentence saying "be
deterministic" still changes nothing; a floor that reddens on a violation is
what holds. A floor is a runner setting where one exists (network off,
parallel random order), one-off evidence where it needs judgment, and a
permanent test only when it meets the bar in `testing-best-practices`.

What construction cannot hold goes to the cheapest existing check that can
express it: the compiler, then rules an existing linter already ships, turned
on and configured, then a behavior test. Craft rules a mainstream linter or
compiler already checks (function length, complexity, warnings as errors,
unchecked results, unused values) are enforced through that tool's
configuration. A project never writes its own checks over its repository,
whether they read source or artifacts such as schemas, manifests, plans, and
docs: no analyzer scripts, linter plugins, custom rule files, or checkers
that re-judge an artifact. Data that crosses a boundary has one typed
definition that each reader parses at its boundary; its test feeds vectors
written from the spec through the product's own parser. A second hand-written
interpreter of the same data is a duplicate, not independence. A finding that
something is not typed is answered with a type. A check that only confirms a
file or string changed prevents no defect and is not added. When no rung can
hold an invariant, because the defect is rare, hard to enforce, or impossible
to catch, a waiver comment at the site says it is unchecked; it does not
become a review deliberation or a contrived example. The waiver is the last
rung, never a shortcut past a redesign. A recurring finding is answered by a
redesign that makes its class unwritable. Retire a check when its defect can
no longer be written or another check covers it.

## Craft

- Write for a human maintainer who has neither this conversation nor the
  author. Reading healthy code should be almost as easy as reading prose in
  the reader's native language; a reviewer who struggles for more than a few
  seconds has found a defect in the code, not in themselves. Nothing from the
  task leaks in: no names, comments, or structure that refer to the request,
  the conversation, the change's history (`new`, `v2`, `fixed`, `updated`,
  `refactored`), or the author's reasoning. When a plain form and a clever
  form are both correct, the plain form ships.
- Types first: define types and data models before logic; make illegal
  states unrepresentable; schema changes drive implementation.
- Assert the invariants code relies on. Programmer errors (violated
  invariants) are asserted and crash; operating errors (bad input,
  timeouts) are handled and reported — never confuse the two. Assertions
  stay on in production: a failed assertion converts a correctness failure
  into an availability failure, which is the cheaper of the two. The unit
  that crashes is the smallest restartable unit that shares no mutable state
  with its neighbours (a request, a feature, an actor); where no such unit
  can be named, it is the process — catching a panic inside shared mutable
  state is not recovery, it is corruption. Assert positive and negative
  space; pair assertions across independent points; prefer the cheaper rung
  (compile-time > runtime > test).
- Put a limit on everything. Every input has a named bound decided at design
  time — message size, batch size, connection count, queue depth — and every
  loop, queue, buffer, cache, retry, and recursion carries an explicit bound
  derived from it; intentionally infinite loops assert it. When the honest
  bound is "the disk" or "the user", pick a number anyway: exceeding a bound
  is an operating error the caller handles, never a growth event. Where the
  inputs are bounded, capacities follow from them, so long-running services
  and data planes size their structures from the bounds at startup and do not
  allocate on the hot path; a structure that is full says so instead of
  growing.
- Optimize for the reader's cognitive load. Keep each function at one level of
  abstraction; order statements with their data flow; keep relevant details
  close and hide only details whose abstraction reduces what the reader must
  hold. Abstraction and indirection are costs too, so add them only when the
  resulting contract is clearer.
- Prefer immutability and pure functions; isolate side effects at system
  boundaries; push `if`s up and `for`s down — parents own control flow and
  state, leaves stay pure. Every branch accounts for its complement: a guard
  clause is right for an exceptional path or short case when the guard itself
  handles or asserts the negative space; use `else` when complementary
  branches are both core logic; an `if` whose other case nothing handles,
  asserts, or rules out by type is the defect. Break up nested control flow
  and mixed boolean expressions into named decisions.
- Errors are handled or propagated, never swallowed. Keep the failure region
  narrow: wrap only the operation whose failure is handled, catch only the error
  meant to be handled, and preserve the original cause when adding context.
  Prefer a specific check to a catch-all: catching every error and continuing
  is rarely safe, and a broad handler behind your own specific check is dead
  code that hides the next failure.
  Validate at system boundaries and only there — a check protecting a state an
  upstream boundary already guarantees is deleted, not kept for safety. Publish
  externally visible state only after every fallible operation succeeds, so a
  failure leaves the prior state intact. External calls carry explicit timeouts
  and bounded retries with backoff; handle edge cases explicitly.
- Refactor with clean breaks: update all callers, complete the migration,
  delete superseded code — supersession is the default; confirm
  replace-vs-add in one line only when genuinely ambiguous. When existing
  structure fights the requested change, make a behavior-preserving prefactor
  unit first when it can stay independently green and focused. Local unpublished
  work may be regrouped this way; changing declared scope, rollout, or a
  published contract still requires confirmation. An unshipped feature has no
  compatibility surface: its experimental behavior is not a contract, so it
  earns no shim, no dual path, and no deprecation window. Tests that redden
  under a supposedly behavior-preserving refactor are first suspected of having
  caught a regression it introduced; only change detectors, as
  `testing-best-practices` defines them, are part of the migration.
- Name clearly and precisely at the code's abstraction level. Omit type words,
  surrounding context, and filler the reader already has; prefer a longer name
  to an ambiguous one. Established abbreviations such as `RPC` are useful when a
  future reader in the domain will understand them; expand obscure or local
  abbreviations. Name booleans positively, use long-form flags, and put units and
  qualifiers last by descending significance (`latency_ms_max`).
- Comments earn their place by explaining intent, rationale, non-obvious
  constraints, or an apparent rule violation. Preserve comments that protect an
  ordering or safety constraint. Replace narration of what code does with clearer
  names or structure, and replace enforceable assumptions with assertions.
  Public API comments state the contract, not implementation details.
- Declare variables at the smallest scope, computed closest to use. A value the
  environment, operator, or caller must choose belongs in configuration; a fixed
  domain invariant belongs in a clearly named constant or type.

## Interfaces and abstraction

- Prefer platform-supported design over a custom wrapper, and derivation from a
  source of truth over cached local state and the cleanup machinery it needs.
- Make the correct call easy and misuse hard. Prefer compiler-enforced contracts,
  then runtime checks, then documentation. Return fully initialized values, use
  domain types for constrained values and units, and group parameters that form
  one concept into a value object. Put lifetime collaborators in construction and
  pass per-call work to the operation.
- Choose defaults by the cost of a mistake. Destructive or irreversible behavior
  is explicit opt-in; environment-specific targets that cannot be chosen safely
  are required rather than guessed. A convenient default is valid only when its
  accidental use is acceptably safe.
- Deduplicate when evidence shows one shared concept that should evolve together,
  not merely identical syntax today. Keep coincidentally equal domain rules
  separate; when evidence is insufficient, tolerate duplication until the common
  abstraction becomes clear. Build for current and planned use cases, not merely
  possible ones. A test seam is justified by its real consumer, but speculative
  generality is not.
- Wrap an external API when doing so clearly bounds change or gives the domain a
  better contract; do not wrap familiar standard types by reflex.
- When a CLI, API, control plane, or automation surface is operated by agents,
  load `agent-operability`. Its inspect/plan/apply/verify contract is the public
  expression of this skill's deterministic, idempotent, atomic, observable,
  evented, and contextual properties—not a second implementation path.

## Threat model

Security-relevant code is written and reviewed against a stated threat model.
A bug is a vulnerability only when it lets an actor do something they could
not already do. Unless the project's SPEC says otherwise, the default model is:

- **Defended against:** network attackers (DNS, routing, Wi-Fi, on-path
  interception), malicious remote peers, and untrusted input: protocol data,
  files, and content the software did not author.
- **Trusted:** root, the user's own account, every other local account on the
  host, physical access, the OS and its configuration, and installed
  executables and dependencies. An actor with shell or disk access already
  owns the machine, and no check in the software changes that.

Hosts are single-tenant. Shared hosts, group-writable package prefixes
(Linuxbrew), permissive ACLs, and other weaker setups a user chooses are that
user's risk and a documented limitation, not a design input. Do not add
ownership, mode, or parent-chain checks whose only purpose is to stop local
accounts.

A project tightens the default in its SPEC when the software crosses a local
privilege boundary: setuid programs or root daemons, multi-tenant services, or
anything acting for a less-privileged local principal. The SPEC names the added
actors, and the rest of the default stands.

A review finding that needs a trusted actor is answered by citing the model.
It does not block, does not count as a second instance of a defect class, and
needs no waiver. The driver may still take a trivial in-scope fix as ordinary
hardening. The model itself can be challenged: a reviewer who argues it is
wrong for the project takes that to the human.

## Properties

Apply each property where its failure mode exists; non-applicability needs no
waiver. Builds and deterministic test harnesses owe determinism, hermeticity,
and isolation. Retried effects, reconcilers, and at-least-once consumers owe
idempotency. Operations that can expose partial state owe atomicity. Side-
effecting and live surfaces owe observability. Async coordination should be
evented, and authority-bearing effects should be contextual. When an applicable
property cannot hold, carry a waiver.

### Deterministic — same inputs, same outputs, same interleaving

Sources of drift: wall clock, unseeded randomness, UUIDs, map and set
iteration order, `readdir` order, thread scheduling, locale, timezone, hash
seeds. The fix is always the same shape: inject the clock, the seed, the id
generator, the scheduler. Never reach for them ambiently.

**Floor:** two checks, and conflating them is the common mistake.
*Repeatability* — run twice with the **same** seed and diff; any difference
is nondeterminism. *Order-independence* — vary only what must not matter
(runner shuffle seed, thread scheduling, map iteration order) and assert the
result is unchanged. A seeded algorithm legitimately produces different
output under a different **algorithm** seed; that seed is an input, so
changing it proves nothing. For engines with a fixed input set, a seeded
simulator whose emitted trajectory is compared against a golden run.

### Hermetic — depends only on declared inputs

Failures: tests that reach the network, tools resolved off `PATH`, absolute
paths, implicit environment variables, host state. Determinism says the same
inputs give the same output; hermeticity says the inputs are all declared.
Reproducible = hermetic + deterministic.

**Floor:** run with the network off, a scrubbed environment, and a foreign
`$HOME`.

### Idempotent — applying twice equals applying once

Three shapes people conflate: the idempotent operation (`f(f(x)) == f(x)`),
the convergent reconciliation (desired state, applied to a fixpoint), and
exactly-once effects via an idempotency key. Its sibling is **atomic**:
idempotency covers the re-run, atomicity covers the interrupted run —
write-temp-then-rename, all-or-nothing apply. Neither alone is crash-safe.

**Floor:** run it twice; assert the second run is a no-op and the diff is
empty. Then kill it mid-apply and run it again.

### Isolated — no interference between concurrent instances

Own tmpdir, own port, own database, own fixtures. Distinct from hermetic:
hermetic is no external dependence, isolated is no inter-instance
interference. A flake that root-causes to shared state between tests is an
isolation defect, not a flake.

**Floor:** run the suite in parallel and in random order.

### Observable — the failure is diagnosable from artifacts alone

Emit structured fields rather than prose-only log lines, with enough context to
identify the failing operation and state.

**Floor:** cause the failure, then diagnose it using only the emitted logs,
metrics, and traces — without re-running and without adding instrumentation.

### Evented — react to state change, don't mistake time for state

Wait on a condition, not a duration. A duration-only sleep used as proof that a
condition now holds is the defect. Bounded backoff before rechecking a condition
is valid when no event source exists; the condition and deadline, never elapsed
time alone, decide success. Two pairings matter more than the property itself:

- **Level-triggered, edge-woken.** Pure edge-triggered systems drop events
  and never recover. The event says *when* to reconcile; the desired-state
  comparison decides *what* to do.
- **Delivery is at-least-once, so consumers must be idempotent.** Evented
  without idempotent is a duplicate-effect bug waiting for its first retry.

**Floor:** reject duration-only success; assert the condition and a deadline.
Where polling is unavoidable, perturb the backoff and prove the same terminal
state.

### Contextual — the call carries what dictates its possibilities

A side-effecting function receives the context of the event that authorizes
it. One structure does four jobs: capability (what this call may do), scope
(deadline and cancellation), provenance (which event, on whose behalf), and
the fields its logs and spans carry. "Dictates the possibilities" is the
load-bearing part — the argument shape should make illegal *effects*
unrepresentable, which is types-first applied to effects and authority
rather than to data.

**Floor:** one assertion per job the context does, and the first is the one
usually missing. *Capability* — construct a context that withholds an
authority and assert the call fails rather than reaching for an ambient
fallback; without this, code that kept its ambient authority passes every
other check. *Scope* — assert cancellation propagates to the leaf.
*Provenance* — assert every record on the path carries the correlation id.

## Waivers

An instance that cannot hold a property, or an invariant no rung can hold,
carries a waiver comment naming the property or invariant, why this instance
can't hold it or why holding it costs more than the defect could, and whether
it is debt or a permanent exemption. For an
invariant, the reason names the design that would make the defect unwritable
and why it does not fit here. Debt names what would remove it.

```
// WAIVER(<property or invariant>): <why this instance cannot hold it, or why it is not worth holding>. <Debt — removed by X | Permanent — X makes it impossible.>
```

The `WAIVER(` tag is literal in every language's comment syntax, so one search
lists every waiver in a project. A waiver is written prose a maintainer can evaluate, never a suppression flag.
A waiver whose reason a redesign within scope would remove is a defect: ship
the redesign instead. The same invariant waived at a second site means its
class needs the redesign. A waiver list that grows without its debt entries
shrinking means the property was stated too strongly — weaken the property,
don't grow the list.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.