# PR#130: Repository Privacy Answer Kept and Renewed in Steps > **WARNING:** This document describes only the change applied in this PR. > It may already be outdated once the next PR is merged. > Historic PR-documentation is not maintained along with new PRs — treat it as a snapshot, not as current documentation. ## The Problem `RepositoryPrivacy.isPrivate` is above the Mutation-CRAP target of 15 in the nightly mutation build of 2026-10-07 and 2026-10-09: | Method | Mutation-CRAP | Complexity | Killed / eligible | |-------------------------------|--------------:|-----------:|------------------:| | `RepositoryPrivacy.isPrivate` | 16.40 | 10 | 9 / 15 | One method decided whether the cached answer still stands, asked the forge, warned about a silent forge and stored the new answer. The tests never touched the exact moment an answer expires, and nothing checked that a silent forge is reported once and not on every retry. ## Non-Goals - No change of the behaviour: the same answers, the same expiry times, the same warning. ## The Scenarios ### Feature: The privacy answer of a repository #### Scenario#130.01: A cached answer expires at exactly its validity So that a repository that changed its visibility is followed within the stated time, and not one poll later or earlier. - **Given** the forge answered for a repository - **When** one second less than the answer's validity has passed - **Then** the cached answer is returned and the forge is not asked - **When** the full validity has passed - **Then** the forge is asked again - The validity is `REFRESH_AFTER` (15 minutes) for a confirmed answer and `RETRY_UNKNOWN_AFTER` (1 minute) for a guess. ##### Verified by - [RepositoryPrivacyUnitTest: a confirmed answer stands for exactly REFRESH_AFTER](../../src/test/kotlin/de/hoennig/werkator/server/RepositoryPrivacyUnitTest.kt) - [RepositoryPrivacyUnitTest: a guess stands for exactly RETRY_UNKNOWN_AFTER](../../src/test/kotlin/de/hoennig/werkator/server/RepositoryPrivacyUnitTest.kt) #### Scenario#130.02: A forge that stops answering is reported once So that the log names the outage without repeating it every minute while the forge stays silent. - **Given** the forge answered for a repository - **When** the forge stops answering and is asked three times in a row - **Then** the warning "Cannot tell whether … is private" is logged once ##### Verified by - [RepositoryPrivacyUnitTest: a forge that stops answering is reported once](../../src/test/kotlin/de/hoennig/werkator/server/RepositoryPrivacyUnitTest.kt) ## The Solution - `Answer.standsAt(now)` says whether a cached answer is still valid. - `isPrivate` returns the cached answer or calls `ask`. - `ask` reads the visibility, warns when a known answer turns unknown, and stores the new answer. Measured locally with PIT on `RepositoryPrivacy`: | Method | Mutation-CRAP before | after | |-------------------------------|---------------------:|------:| | `RepositoryPrivacy.isPrivate` | 16.40 | 6.04 | | `RepositoryPrivacy.ask` | new | 6.11 | | `Answer.standsAt` | new | 3.00 | The gate stays at 15. ## Prerequisite PRs - PR#129 — this branch is stacked on it, for the version and the release notes. ## Follow-up PRs - PR#131 splits two more methods of `ConfigLoader` into smaller steps, so that their scores drop below 15. `ConfigLoader.renameLegacySandbox` is at 15.93. `ConfigLoader.checkRestartsInstance` is at exactly 15.00: one more surviving mutant would put it above the gate.