brick/docs/architecture/policy.md

83 lines
3.3 KiB
Markdown

# Declarative architecture policy
Brick policy is a small, versioned consumer of the canonical building graph.
It extends `brick check`; it does not introduce a second gate engine or infer
relationships that are absent from the model.
## Policy schema 1
A policy is JSON with exactly three top-level fields. Unknown fields and unknown
rule kinds fail closed.
```json
{
"policy_schema_version": 1,
"scope": {
"path": ".",
"excluded_directories": [],
"p4_frontend": "lexical"
},
"rules": [
{
"kind": "forbid-dependency",
"id": "api-must-not-call-storage",
"source_path_prefix": "src/api",
"target_path_prefix": "src/storage",
"edge_kinds": ["calls", "imports"],
"max_matches": 0
}
]
}
```
The policy scope must exactly match the building's schema-v4 scan scope,
including the selected P4 frontend and the sorted, unique exclusion list.
Scope paths and rule prefixes must be normalized repository-relative paths;
absolute or drive-qualified paths, backslashes, empty components, `.`
components, and `..` are rejected (`.` alone means the entire repository).
Rule IDs are required and unique. Edge kinds are required, unique, and limited
to canonical dependency kinds: `calls`, `imports`, and `inherits`. Containment,
definition, finding/Flags, and unknown wire values cannot be relabeled as
architecture dependencies by policy.
Path prefixes are component-aware: `src/api` matches `src/api/handler.rs` but
not `src/apiary.rs`. `max_matches` is explicit; zero forbids every matching
relationship, while a larger value expresses a bounded exception without
hiding the matched edges.
## Evaluation and evidence
Before evaluation, Brick validates the building schema and exactly-one
repository identity, verifies exact scope equality, and rejects duplicate node
or edge IDs plus edges with missing source or target nodes. Rules are evaluated in rule-ID order and matched edges in stable
edge-ID order.
Policy never changes evidence confidence or lane. Each match in the result
contains the complete canonical edge plus complete source and target nodes, so
backend, Syntactic/Heuristic/Imported/Symbolic lane, producer-local confidence,
attributes, and provenance remain inspectable.
Policy result JSON has `policy_result_schema_version = 1` and records the input
policy schema, building schema, absolute execution root, stable repository ID,
scope, overall pass state, and every rule's ordered matches.
## `brick check` integration
```text
brick check build/brick/current.json --min-score 70 \
--policy architecture-policy.json \
--policy-result-json build/brick/policy-result.json
```
`--policy-result-json` requires `--policy`. Complete results are written before
a rule failure is returned. Policy failures join the existing score, cycle,
unresolved-dependency, and optional structural-diff failures under the same
`structural gate failed` result. Without `--policy`, existing check behavior is
unchanged.
Checked-in positive, clean-negative, and unknown-wire fixtures live in
`tests/fixtures/policy/`. This initial slice supports repository-relative
forbidden dependency boundaries only. Diff-count budgets remain the explicit
stable-ID diff gates described in `docs/architecture/structural-diff.md`; future
policy rule kinds must be versioned rather than inferred from extra JSON keys.