Quickback Docs

Diagnostics

The compile-time authz / authn analyzer. Reads the lowered policy IR and flags empty or shadowed permissions, unreachable roles and views, capability-ceiling breaches, the not-over-resource null-trap, and pushdown cost — warn-by-default so upgrades never break, with a QUICKBACK_AUTHZ_STRICT opt-in that turns every warning into a hard compile error.

Quickback compiles your authorization model into a single normalized policy IR — relations, permissions, arrows, scopes, grants, and per-resource firewalls — and then runs a set of static checks over it. The analyzer never changes what's emitted; it reports problems it can prove from the policy graph: a permission that can never be satisfied, a scoped role no grant reaches, a resource that hands a scope role more than its profile allows, a negation that can silently pass.

The console channel

Diagnostics render to the existing [quickback:authz] / [quickback:authn] console channel — the same prefix the compiler has always used for security warnings, so any CI grep you already key on keeps working. Each line carries a stable, greppable code:

[quickback:authz] AUTHZ_EMPTY_PERMISSION: permission "event:locked" can never be satisfied — it requires organizerOf AND its negation simultaneously.
  at resource=sessions authz.permissions["event:locked"]
  hint: Remove the contradictory arm, or split into separate permissions.

The first line stays greppable ([quickback:<channel>] CODE: message); the source location and fix hint render on continuation lines.

Warn by default, opt-in strict

The analyzer is warn-by-default, compile-continues. This is deliberate: the analyzer runs on the shared compiler that serves every project, so a new check must never break an existing build on upgrade. In the default path every diagnostic — including the one check authored at error severity (the capability ceiling) — is rendered as a warning line and the compile proceeds.

Set QUICKBACK_AUTHZ_STRICT=true to promote every warn to error. Under strict mode the compile fails (throws an aggregate error listing the codes) if any diagnostic is — after promotion — an error. info lines (the pushdown-cost report) stay informational and never fail a build.

# warn-only (default): prints diagnostics, compile succeeds
quickback compile

# strict: any warn or error fails the compile
QUICKBACK_AUTHZ_STRICT=true quickback compile

The analyzer is compile-time only — zero runtime blast radius. A defect in the analyzer itself is caught and downgraded to a single warning in the default path, so an analyzer bug can never take down an otherwise-valid compile. (Strict mode re-raises, because there the throw is the intended hard failure.)

Authz codes

These read the permission graph projected from the policy IR. All are warn severity (so info for the pushdown report) except the capability ceiling, which is authored as error.

CodeSeverityWhat it catches
AUTHZ_EMPTY_PERMISSIONwarnA permission that can never be satisfied — e.g. allOf(a, not(a)), which requires a fact and its negation at the same AND-level.
AUTHZ_SHADOWED_ARMwarnAn anyOf arm subsumed by a broader arm: a leaf X and an allOf(X, …) in the same union — the narrower arm can never widen the result.
AUTHZ_UNREACHABLE_ROLEwarnA scoped role declared under authz.scopes with no grant profile — it can authorize no read, action, or channel, so it's dead config.
AUTHZ_UNREACHABLE_VIEWwarnA grant's read names a resource:view whose resource has no firewall — no role can reach that view.
AUTHZ_PUSHDOWN_COSTinfoPer-permission report: how many SQL subqueries the permission lowers to, plus the max recursive-CTE depth (from recursive arrows). Advisory, never fails a build.
AUTHZ_CAPABILITY_CEILINGerrorA resource's firewall grants a scope:<kind>:<role> role read access beyond its capability profile — either the role has no profile at all, or the profile doesn't list this resource.
AUTHZ_NOT_OVER_RESOURCEwarnA not whose operand resolves to a resource (SQL) siteNOT EXISTS over a nullable join can silently pass (the null-trap). The analyzer resolves the operand's site from its leaves, so it fires even when the lowering left the site unset.

A few codes are reserved in the diagnostic enum for the milestones that emit them and don't fire on a shipped config today: AUTHZ_UNBOUNDED_RECURSION (an unbounded recursive arrow with no claim path — currently a hard compile error raised at config validation, before the analyzer runs), AUTHZ_UNENFORCEABLE_FACT, and AUTHZ_CAVEAT_SITE_MISMATCH (M3 caveats).

The capability ceiling

The one error-severity authz check. It is the M0.2 deliverable that backs scope grant profiles: a scoped role is deny-by-default and may touch only what its grants profile lists. The analyzer walks every resource firewall, follows each { permission } arm into the permission graph to find the scope roles it references, and fails the build (in strict mode) if a resource grants a scope role access the profile doesn't cover. In the default path it warns loudly. This is what makes the grant profile the single auditable manifest of what an external principal can see.

Authn codes

Four structural authentication checks — proving properties over the generated route + credential surface rather than the authz policy:

CodeSeverityWhat it catches
AUTHN_ROUTE_COVERAGEwarnA route that reaches data with an unclassified auth gate and isn't declared PUBLIC — the signup / flag-gap bug class (data delivered to an unauthenticated ctx).
AUTHN_SECRET_CONSISTENCYerrorA credential's mint site and verify site don't share key / issuer / audience — every minted token would fail verification (the ws-ticket "401 on every upgrade" trap).
AUTHN_CREDENTIAL_DELIVERYerrorA fire-and-forget credential send (the OTP-email shape) not anchored to waitUntil / await — the Worker may drop the promise and never deliver (the OTP-500 bug class).
AUTHN_CLAIM_PROVENANCEerrorAn identity ctx field written from request input rather than a credential verifier — client-asserted identity, which is forbidden.
AUTHN_SURFACE_INVARIANTwarn / errorA surface contract breach: an /mcp or agent route not gated bearer-only (warn), or an INTERNAL-gated route mounted on an HTTP-reachable surface (error).

These check definitions are wired and fully unit-tested, but their inputs — the per-route and per-credential metadata (RouteNode / MintSite / VerifySite / ClaimWrite) — are not yet emitted by the route, middleware, and credential generators. Until those generators emit that metadata the analyzer runs the authn checks against empty route/credential graphs, so they are effectively no-ops on a real compile. The check logic needs no change when the metadata lands — the route/credential coverage activates the moment the generators emit it. The authz / permission-graph checks above run unconditionally today, because the policy IR is always present.

Reading the pushdown-cost report

AUTHZ_PUSHDOWN_COST is an info line per permission that pushes down to SQL — it never fails a build, but it surfaces the query cost of an authorization rule before you ship it:

[quickback:authz] AUTHZ_PUSHDOWN_COST: permission "section:inTree" lowers to 1 SQL subquery, recursive CTE depth 6 (sites: resource).

A high subquery count or a deep recursive CTE (from a recursive arrow) is a signal to reconsider the rule — not an error, but worth a look.

See also

  • Permissions — the anyOf / allOf / not DSL the empty / shadowed / not-over-resource checks analyze.
  • Arrows — recursive-CTE depth feeds the pushdown-cost report; the unbounded-recursion guard is a hard error.
  • Scopes & capability grants — the grant profiles the capability-ceiling check enforces.
  • Firewall — the { permission } arms the ceiling check follows into the permission graph.

On this page