Skip to content

Lint Rules

Rules under the CED prefix. The complete generated table is on All Rules; this page is the reasoning.

The two engines, and why there is only one

Section titled “The two engines, and why there is only one”

Cedar’s own validator runs in-process through @cedar-policy/cedar-wasm — the real thing, not a reimplementation. It answers “is this policy well-formed against this schema”.

Everything else is a TypeScript check. There is no cedarGate(), because organizational policy in chant is post-synth checks and a second policy engine would duplicate the lint engine.

permit (principal, action, resource);

Every scope unconstrained, no conditions. Legal Cedar, validates clean, grants everything to everyone. The rule is env-aware:

EnvironmentVerdict
dev / localwarn
stagingwarn
prodfail

Env-aware rather than absolute because an absolute rule gets suppressed the first time it fires during development, and a suppressed rule protects nothing. A permit with any constrained scope position, or any when/unless, is not bare.

A policy naming an entity type or action the schema does not declare fails everywhere, dev included. Two failure modes hide behind it:

  • The typoApp::Documnt. Generated classes make this a compile error before any check runs; it survives only inside when/unless expression strings.
  • The silent no-op — a scope naming an absent entity type parses, and Cedar’s request-envelope resolver answers “success, nothing”. The policy is well-formed, deployable, and can never fire.

The differentiator, and the thing no Cedar tool can express: Cedar only ever sees policies, while a chant build holds the policies and the infrastructure they govern in one entity graph. So a post-synth check can span both:

  • an entity id in a policy references an actual resource declaration
  • every declared bucket is covered by at least one forbid
  • no schema action lacks any policy

These are ordinary post-synth checks. Nothing exotic — they just need both halves in the same build, which is the arrangement chant already has.

Terminal window
npx chant cedar coverage # schema -> generated artifacts

The MCP tool asks the other half:

cedar:coverage { "path": ".", "format": "text" }

It builds the policy set, hands each policy to Cedar’s own getValidRequestEnvsPolicy alongside the schema, and reports:

FieldMeaning
uncoveredDeclarations no policy can apply to
forbidOnlyDeclarations reachable only from a forbid — nothing grants them
inertPolicies whose request envelope is empty; they can never fire
unresolvedPolicies the resolver rejected outright
parseErrorsWhy the set would not split into policies

Container entity types — the ones that appear in no action’s appliesTo and exist only to be in — show as uncovered even under a bare permit. That is the resolver telling the truth: no request can name them.

The post-synth checks encoding all of the above are INTENTIUS/chant#1651. Today the lexicon ships the source-level rule set and the validation plumbing; the checks that span policies and estate land there.