Managed rollouts: ACP_REQUIRE_ENROLLMENT blocks unenrolled machines instead of warning - #23
Merged
Conversation
…nstead of warning An admin who pushes the hook fleet-wide (Codex requirements.toml, Claude Code managed settings, Cursor enterprise hooks) sets ACP_REQUIRE_ENROLLMENT=1 in the managed hook command or managed env. With no workspace credential present the hook now denies each PreToolUse call with the enrollment step, writes a BLOCKED lapse line, and refuses to fall back to LOCAL mode. Without the flag nothing changes: the default posture is still run-ungoverned-and-warn. Gateway-unreachable posture (#385) is untouched.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds one env flag,
ACP_REQUIRE_ENROLLMENT=1, for admin-pushed hook rollouts (Codexrequirements.toml, Claude Code managed settings, Cursor enterprisehooks.json).With the flag set and no credential at
~/.acp/credentials/~/.acp/proxy-key/ACP_BEARER_TOKEN:PreToolUse→permissionDecision: "deny"with the enrollment step (authorize page + one-line write of the key).systemMessageonly.~/.acp/lapse.loggets aBLOCKED\tno-credentialsline (wasUNGOVERNED).ACP_LOCAL=1or apolicy.json) does not satisfy the gate: managed means the workspace policy.Without the flag, behaviour is byte-identical to today (run ungoverned, warn once per session, log a lapse).
Why
A managed hook is the same file on every machine and can't carry a per-user key. Today an unenrolled seat runs ungoverned with a warning, which is the right default for self-serve installs and the wrong one for a fleet an admin believes is covered. The flag is the admin's explicit opt-in. Gateway-unreachable posture (#385) is deliberately untouched: this gate is about no credential, not no gateway.
Tests
New
test/managed-mode.test.mjs(6 cases: default posture unchanged, deny on PreToolUse, deny on every call, LOCAL doesn't satisfy, non-Pre events message-only,0/unset = default).node --test: 111 pass, 0 fail.Docs: per-harness recipes land on agenticcontrolplane.com/docs/enterprise (separate PR). Scoped in davidcrowe/gatewaystack-connect#943.