Skip to content

[CHORE]: Retire "all" APL keyword. #143

Description

@terylt

Summary

Now that policy bundles are a first-class top-level groups: section (PR #131), the
one remaining issue is the reserved all name. all is a magic key that means
"apply to every request" — it is not something a route ever opts into, yet it sits in
the same map as the opt-in bundles. This issue tracks moving the always-on policy to a
dedicated global.authorization block (beside the existing global.authentication),
so groups: holds only opt-in bundles with no reserved names.

Split out of the PR #131 review
(araujof) because it is (a) an open design decision, (b) cross-crate, and (c) orthogonal
to that PR's thesis (RFC 8693 actor tokens + subjects). PR #131 ships groups: with
all kept working as the reserved always-on group — this is the interim state below.

Current state (as of PR #131)

  • Bundles live at top-level groups: (canonical); global.policies: is a deprecated
    alias, merged into the same internal map at parse time.
  • all is still a reserved key inside that bundle map. It works as it always has:
    • its plugins are always included (cpex-core::config::resolve_plugins_for_entity,
      step 1: config.global.policies.get("all"));
    • the identity resolver's always-on layer is the separate global.authentication:
      block (GlobalConfig.identity), not the all group.
  • This is effectively option (a) below, documented as interim in the cookbook's
    scoping table.

The decision: (a) vs (b)

(a) Keep all as a reserved key inside groups:. Document that groups.all
applies to every request and every other key is opt-in via a route's groups: / tags.
Minimal change; keeps the magic name.

(b) Retire the magic name. Move the always-on
policy to a dedicated global.authorization block, symmetric with the existing
global.authentication. Then groups: holds only opt-in bundles — no reserved names,
three clean top-level concerns:

global:
  authentication: [jwt-user]        # always-on identity  (exists today)
  authorization:                    # always-on policy    (NEW — replaces groups.all)
    pre_invocation:
      - "require(role.employee)"
groups:                             # opt-in bundles only, no reserved names
  hr-tools:
    authentication: [jwt-manager]
    authorization:
      pre_invocation: [ "require(role.hr)" ]
routes:
  - tool: get_compensation
    groups: hr-tools

Scope

The always-on all layer is applied in two places, so both must move:

  1. cpex-coreresolve_plugins_for_entity step 1 reads global.policies.get("all")
    for always-on plugins. Point this at global.authorization (+ the always-on
    plugins it carries).
  2. apl-cpex — always-on authorization (APL) steps compile through the visitor's
    layers. Confirm how the all bundle's authorization: steps reach every route today
    (tag_layers["all"] vs global_layer) and route them from global.authorization
    instead.

global.authorization should accept the same shape as a group's authorization: /
plugins (reuse PolicyGroup or a focused subset).

Back-compat (required)

  • all (at groups.all and the deprecated global.policies.all) must keep working
    as a deprecated alias for global.authorization, merged at parse time. Emit a
    deprecation tracing::warn! when the all spelling is used.
  • Existing configs (the CPEX demo cpex.yaml, praxis fixtures) must load unchanged.

Acceptance criteria

  • global.authorization block accepted and applied always-on for both authorization
    steps and plugins.
  • all (both locations) still works, merged into global.authorization, with a
    deprecation warning.
  • Both application sites moved (cpex-core resolver + apl-cpex always-on layer), with
    tests proving an always-on rule from global.authorization fires on a route that
    declares no groups.
  • Cookbook scoping table updated: Global row → global.authorization; drop the
    "reserved all" interim note.
  • configuration.md documents global.authorization and the all deprecation.
  • cargo fmt --check + cargo clippy -- -D warnings clean; workspace green.
  • Linter runs cleanly (make lint)
  • CI passes with no regressions
  • Docs/tooling updated (if applicable)
  • Security scans pass

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    • Status
      Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions