NAP — Negative Authority Profiles
Module: src/convergence_io/nap.py · Principle: P2 (Authority / Consent Gates), denial form · Composes: M1 (Dynamic External Predicates) Status: Implemented + unit-tested. Python reference contract; not imported by the live JS chat path (see README).
What it is
NAP is the inverse of a capability claim: it defines what agents are explicitly denied from doing. The load-bearing rule —
A hard denial cannot be overridden by a capability claim. Denials are enforcement boundaries, not preferences.
It composes with M1: external deny-lists (OFAC SDN, BIS Entity List, etc.) can be loaded as NAP entries and refreshed on a schedule. When a source is unreachable the runtime degrades safely (keeps the last known denials rather than failing open).
Core types / API
NegativeAuthorityProfile— one denial profile:denies_action(action_type)·denies_provider(provider_id)·denies_boundary(boundary)·denies_data_class(label)— the four denial axes (composes with DCF.md viadenies_data_class).is_expired()— time-boxed profiles (e.g. a refreshed external list).can_override(tier)— whether a given tier may override this profile (hard denials returnFalsefor everyone).to_dict().
AuthorityGate— the enforcement point:add_profile(profile)/remove_profile(profile_id)check(action_type, provider_id="", boundary=..., data_class=..., tier=...) → AuthorityResultactive_profiles()— introspection.
AuthorityResult—{allowed, denied_by, reason, ...}.- Factories:
dreamer_safety_nap()(baseline Dream-Journal safety denials) and
local_only_nap() (deny all non-local providers — the offline/sovereign profile).
How it composes
NAP runs before CCF in the gate order: a denial is a hard floor under capability. PCSF's fallback chain is also clamped by NAP (denies_provider), so a denied provider is never selected even if it's the only routable one — the request fails closed instead.
Status & gaps
- Implemented with the four denial axes + override-by-tier + safe-degrade contract; covered by
- The M1 external-list loaders (the actual OFAC/BIS fetch + schedule) are referenced by the
contract but are a separate ingestion concern — NAP consumes entries, it doesn't fetch them.