nisse-review: repository patterns, and the wall checked every round
At bring-up, nisse-review read no repositories: Gitea's /user/repos leaves out a public repository's Read collaborators, so dev/nisse never showed up. `repositories` now holds patterns (dev/nisse, dev/*, */*) matched against every repository the account can read, public ones included (an organization's or user's list, or the instance's search); unset, it is /user/repos as before. A configured repository it can't read is left out with an oplog line. The read-only wall (R3) is checked every round, not only at startup: an account granted push or admin while running stops (exit 3) rather than review on. nisse-core's Gitea client gains GiteaNotFound for 404s, owner_repositories and visible_repositories. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J5Utyfzw7gF7UhjRDEtjTk
This commit is contained in:
1 parent
52c6704b17
commit
2139ddd05c
12 files changed
+283
-44
No files matched your search
@@ -15,6 +15,7 @@ from nisse_core.models.context import BudgetedClient
|
||||
from nisse_core.models.llm import LiteLLMClient
|
||||
from nisse_core.oplog import OpLog
|
||||
from nisse_core.state.cancel import Cancel
|
||||
from nisse_review.access import AccessRefused, check, reviewed
|
||||
from nisse_review.config import ReviewConfig
|
||||
from nisse_review.review import Reviewer
|
||||
from nisse_review.scheduler import Scheduler
|
||||
@@ -41,23 +42,18 @@ class Built:
|
||||
self.store.close()
|
||||
|
||||
|
||||
def check_access(gitea: GiteaClient) -> tuple[str, list[str]]:
|
||||
"""Who it is and what it reads (R3): read only. An account that can push
|
||||
to, or administer, a repository it reviews is refused: its hard wall is
|
||||
that it can't change what it reviews."""
|
||||
def check_access(
|
||||
gitea: GiteaClient, patterns: frozenset[str] | None, oplog: OpLog
|
||||
) -> tuple[str, list[str]]:
|
||||
"""Who it is and what it reviews (R1, R3): read only. An account that
|
||||
can push to, or administer, a repository it reviews is refused: its hard
|
||||
wall is that it can't change what it reviews. The scheduler checks again
|
||||
every round (``access``)."""
|
||||
account = gitea.whoami()
|
||||
repos = gitea.readable_repositories()
|
||||
too_much = [
|
||||
repo
|
||||
for repo in repos
|
||||
if (perms := gitea.repository(repo).get("permissions") or {}).get("push")
|
||||
or perms.get("admin")
|
||||
]
|
||||
if too_much:
|
||||
raise StartupError(
|
||||
f"{account} can write to {', '.join(too_much)}: nisse-review's "
|
||||
"account must have read access only (Part R, R3)"
|
||||
)
|
||||
try:
|
||||
repos = check(gitea, reviewed(gitea, patterns, oplog), oplog)
|
||||
except AccessRefused as exc:
|
||||
raise StartupError(str(exc)) from exc
|
||||
return account, repos
|
||||
|
||||
|
||||
@@ -100,7 +96,7 @@ def build(
|
||||
) -> Built:
|
||||
oplog = oplog or OpLog(AGENT)
|
||||
gitea = gitea or GiteaClient(config.gitea_url, config.gitea_token)
|
||||
account, repos = check_access(gitea)
|
||||
account, repos = check_access(gitea, config.repositories, oplog)
|
||||
client = client if client is not None else llm_client(config)
|
||||
config.state_db.parent.mkdir(parents=True, exist_ok=True)
|
||||
store = StateStore(config.state_db, oplog=oplog)
|
||||
@@ -146,6 +142,6 @@ def build(
|
||||
scratch=Path(scratch),
|
||||
poll_s=tuning.review.poll_s,
|
||||
attempts=tuning.review.attempts,
|
||||
only=config.repositories,
|
||||
patterns=config.repositories,
|
||||
)
|
||||
return Built(scheduler, account, repos, store, gitea)
|
||||
Reference in new issue
Block a user