diff --git a/docs/adr/2026-10-11-public-personal-auto-authorization.md b/docs/adr/2026-10-11-public-personal-auto-authorization.md index 96b4e61d1c..54831d8757 100644 --- a/docs/adr/2026-10-11-public-personal-auto-authorization.md +++ b/docs/adr/2026-10-11-public-personal-auto-authorization.md @@ -2,7 +2,7 @@ ## Status -Proposed in ContextualWisdomLab/.github#2607; the maintainer's requested endpoint and model are explicit session instructions. +Accepted on 2026-10-13 after ContextualWisdomLab/.github#2607 merged. The maintainer's requested endpoint and model are explicit session instructions. Runtime App review and approval remain separate acceptance evidence. ## Context and decision drivers diff --git a/tests/test_noema_premerge_production_caller.py b/tests/test_noema_premerge_production_caller.py index 76b4e17473..867bb71846 100644 --- a/tests/test_noema_premerge_production_caller.py +++ b/tests/test_noema_premerge_production_caller.py @@ -30,6 +30,17 @@ def test_normal_noema_has_no_unprovisioned_external_admission(): assert 'noema-accepted-tooling.json' not in source +def test_normal_noema_uses_read_only_metadata_then_scoped_app_publication(): + """Ordinary reviews read PR scope before granting a fresh write token.""" + source = (ROOT / '.github/workflows/noema-review.yml').read_text() + metadata = source.split(' - name: Refresh read-only Noema GitHub App metadata token after model\n', 1)[1].split(' - name:', 1)[0] + publication = source.split(' - name: Refresh repository-scoped Noema GitHub App token for publication\n', 1)[1].split(' - name:', 1)[0] + assert 'permission-pull-requests: read' in metadata + assert 'permission-pull-requests: write' in publication + assert source.index('Prepare Noema model verdict\n') < source.index('Refresh repository-scoped Noema GitHub App token for publication\n') + assert source.index('Refresh read-only Noema GitHub App metadata token after model\n') < source.index('Refresh repository-scoped Noema GitHub App token for publication\n') + + def test_actual_cli_refuses_missing_independent_pins(tmp_path): """An unconfigured production caller cannot silently return success.""" result = subprocess.run(