Problem/Motivation

Dual-venue record for GitHub #77.

A policy profile's acknowledged_role_permissions is a flat list of role_id:permission strings. That makes an acknowledgement global, which is wrong whenever a grant is legitimate on one environment and a violation on another.

Concretely: a config-editing role needs administer site configuration on dev, because configuration is exported to code and code changes start on dev. It must not have it on prod. Acknowledging it today makes the role audit pass everywhere — asserting a boundary prod does not have, which defeats the check rather than recording a decision.

Proposed resolution

Extend the grammar with an optional environment scope:

mcp_config_editor:administer site configuration@dev

Unscoped entries keep working unchanged.

The environment comes from settings.php, not from config:

$settings['mcp_sentinel.environment'] = 'dev';

This is the load-bearing part. Exported configuration travels dev to prod, so an environment recorded in config is precisely how prod comes to believe it is dev. settings.php is per-environment by construction and is not exported.

It must fail closed. No declared environment means a scoped acknowledgement does not apply, so the violation is reported. A site that forgets to set it gets the strict answer, never the permissive one.

VIOLATION_IS_ADMIN stays outside this: an is_admin role cannot be acknowledged into compliance, because enumerating its permissions proves nothing.

Remaining tasks

Implemented in GitHub PR #83, awaiting review and merge. The module ships the mechanism only — environment names belong to the site, so no environment naming or hostnames are hardcoded.

Comments

jmcerda created an issue. See original summary.

jmcerda’s picture

Status: Active » Fixed

Fixed on the 1.x branch.

`acknowledged_role_permissions` now accepts `role_id:permission@environment` alongside the unscoped form, and the environment name is read from `$settings['mcp_sentinel.environment']` in settings.php — never from config, because exported configuration travels dev to prod and an environment recorded in config is precisely how prod comes to believe it is dev.

It fails closed: with no environment declared, a scoped acknowledgement does not apply and the violation is reported. A site that forgets to set it gets the strict answer. That path has its own test, since it is the one that matters.

`VIOLATION_IS_ADMIN` stays outside the mechanism — an `is_admin` role cannot be acknowledged into compliance, because enumerating its permissions proves nothing.

One implementation note worth recording: the check *constructs* `role:permission@environment` and compares, rather than splitting the entry on `@`. Parsing would misread any permission whose own name contains an `@`.

The module ships the mechanism only. Environment names belong to the site, so none are hardcoded.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

jmcerda’s picture

Version: 2.0.1 » 2.1.0

Fixed in 2.1.0 (GitHub #77 / PR #83). Environment-scoped acknowledgements: role_id:permission@environment from $settings['mcp_sentinel.environment'].

jmcerda’s picture

Status: Fixed » Closed (fixed)

Shipped in 2.1.0. Closing after release.