Workspace tools · Managed installations and owner retrieval
Managed installations and owner retrieval
For an organization repository, an owner or admin publishes a required policy, each developer accepts it on their own installation, and Connections shows per installation what arrived. A case can ask an enrolled installation for missing evidence, and a pull request check names commits the evidence does not cover.
For: the team owner or admin who investigates incidents on a managed GitHub repository, and the developer whose installation the policy covers
What it does, and why it helps
A managed repository is one where an owner or admin has published a required policy on the repository page. The card is called Managed installations. Publish required policy sets the scope (captured production, performance, security and cost incidents, traces, coding sessions and transcripts for this GitHub repository) and the retention of new transcripts, 7 to 365 days. It also sets Case evidence hold (days past the window): how long a team owner or admin may keep this repository's evidence for an open case after its window ends. The default is 30, the total never passes 365 days, and 0 publishes a policy with no hold clause. Pause managed disclosure stops it without deleting anything. A new policy version cancels earlier acceptances, so every installation accepts again.
A developer accepts on the desktop app, under Settings, Managed GitHub repositories: tick I accept policy version N for owner/repo on this installation and press Accept this policy. The policy text shows the hold clause with its days and its 365-day ceiling, or says the policy has none. The app says what acceptance does not do: Acceptance alone does not verify capture or complete evidence delivery. Once accepted, the capture service uploads captured Claude Code and Codex session files for that repository once an hour, even when optional cloud sync is off. Other tools are not captured. The installation reports a tool as uncaptured when the repository holds its history or configuration file (Aider, Cursor, GitHub Copilot, Windsurf, Cline, Continue, Gemini CLI), and the repository then reads no capture adapter for that tool. It checks only that the file exists and never opens it. Uploads resume across restarts, and offline capture stays on the machine until an upload is verified.
Connections, at the top of /team/connectors, shows every enrolled installation of each managed repository you manage: the adapters it captures, its last upload and last verified receipt, this repository's unsent transcript files, bytes and oldest content, whether it reported in the last 65 and a half minutes (one hourly report interval and the five and a half a daemon allows itself), the snapshots stored in the cloud, and open owner requests. Each cell names its source and time, and a value nobody reported reads not reported. The required developers come from the stored GitHub collaborator list, refreshed hourly, never guessed from the team roster.
On a hosted case, Evidence coverage lists seven evidence families and their state. The Runtime event payload row reads partial when the case's stored trace was sampled upstream or is missing a parent span, and the matrix shows how each stored trace joins the case, as the production evidence guide describes. Retrieve missing evidence checks what is already stored first, then queues a request to each linked installation. Request only this family, on the Transcript and Tool records rows, asks for that family alone; the installation checks the whole source's repository scope and sends only those records with the source byte ranges they came from. Source receipts cannot be asked for alone, and the button says why. Installations are never reached from outside: each one polls out on its five-minute cycle, collects the named session and uploads it. An offline installation keeps the request queued for up to 72 hours. Finally, the RepoOps managed evidence check on each pull request fails commits whose session has no verified snapshot or whose author's installation is not syncing. It covers commits in the pull request; it cannot see a clone or an offline edit that never reaches one.
A check does not deny access. To do that, turn on Restrict repository access to enrolled developers under Repository access on the repository card. The GitHub App installation must hold Administration: Read and write on the repository; RepoOps reads the permission from GitHub each time, and without it the option is disabled, names the missing permission and links the installation's GitHub settings page. The dashboard cannot enforce access without it. Preview changes (dry run) lists each direct collaborator who would lose access or be lowered to read and why: no linked team member, no installation on the current policy, an installation that is not syncing (named in the same words the managed evidence check uses, because both read one rule), or a bot with no exception. It also lists who is still inside the grace period, who is never changed (repository admins and custom roles, a bot with a bot exception, a person with an emergency access exception, and an organization member with a direct grant, whose access may also come from a team) and who reaches the repository through a team or the organization's base role, which RepoOps does not change. Nothing changes until you tick the confirmation for that exact list and apply it; if the list changed in between, RepoOps asks you to preview again. Each change is written to the audit record before and after the GitHub call and has a Restore previous access button.
Emergency access exceptions follow a verified GitHub account id, so renaming an account keeps its exception and reusing an old login does not inherit it. If an older exception has no verified identity, revoke and renew it before enforcing access. Restoration verifies the original account's current login. Each person's eligibility is rechecked during a batch, so newly enrolled or excepted developers are protected.
The pain. An incident points at a session that ran on a developer's laptop. The laptop is offline, the transcript never left it, and nobody knew until the evidence was needed.
The point of view. For a repository the organization owns, enrollment and sync are conditions of working on it. The owner should see whether the evidence arrived, not whether a device is online, and a gap should read as a gap.
What gets easier. Knowing what you can investigate before you need to. Connections names the installation that is behind, the case names the family that is missing, and one button asks for it.
When it helps. On a paid hosted team with the GitHub App installed on an organization repository whose developers use Claude Code or Codex through the RepoOps desktop app.
Its limits. Only Claude Code and Codex session files are captured. Unsent counts read as a floor until the capture scan finishes a full pass, and a Codex session file is counted once the scan reaches it. Diagnostics always reads unsupported in the case matrix. A request asks for a whole session, the transcript alone or the tool records alone; source receipts cannot be asked for alone. Tool records are recognized by each tool's own record shape, and a record too long or malformed to classify is left out and the request reads partly received. The check becomes a merge gate only after someone adds it to branch protection. The access restriction changes direct collaborator grants only, never teams or organization membership, and needs the Administration permission, which the RepoOps GitHub App does not request by default; a restore may arrive as a GitHub invitation the person must accept. Nothing here has been verified on a real tenant and device end to end.
Understand it in 30 seconds
Read the narration
- 0:00 A merged change names a session.
- 0:02 Did its evidence ever reach your team?
- 0:06 Publish a required policy.
- 0:08 Each developer accepts it on their own installation.
- 0:13 Connections shows each installation's last receipt and unsent backlog.
- 0:17 On a case, Retrieve missing evidence queues a request the device collects on its next poll.
- 0:23 A pull request check flags commits without verified evidence.
- 0:27 Work outside a pull request stays unseen.
Synthetic example. Read the guide
Read the narration
- 0:00 A failed evidence check does not remove repository access.
- 0:06 The App needs Administration permission.
- 0:08 An owner chooses the restriction and grace period.
- 0:13 Preview affected collaborators, then confirm that list.
- 0:17 Changed eligibility stops stale previews. Admins and exceptions stay protected.
- 0:23 Review the audit record and restore previous access.
- 0:26 Restoration verifies the original GitHub account.
Synthetic example. Read the guide
Where to find it
- Desktop: Settings, Managed GitHub repositories, where a developer accepts a policy on this installation. Runtime health on the six primary pages shows transcript delivery.
- Hosted: repoops.ai/team/repos/<repo> for the policy and the required-check exceptions; /team/connectors for coverage (the sidebar calls it Connections); the Evidence coverage section of any hosted case.
- API:
/api/team/managed-repositories, /api/team/evidence/requests, /api/ai-incident-cases/<id>/coverage
When to use it
A case whose transcript never arrived
Situation. A production case on a managed repository links two sessions. The Evidence coverage section reads 4 of 7 evidence families captured, with Transcript partial.
What you do. Press Retrieve missing evidence. Open the Coverage matrix to see the family rows and Installation requests for this case's sessions.
What you see. The result reads 1 new requests queued; 1 already queued, and says stored content was checked first. The request row reads queued until the installation polls, then collecting, then received or partial with a reason such as source-not-found.
What it establishes. Either the transcript is stored and verified, or the case says exactly why not. Nothing reads complete that is not.
An installation that stopped syncing
Situation. A developer's laptop went to sleep for a week. Their pull request fails the RepoOps managed evidence check with the author's enrolled installation is not syncing (health report stale).
What you do. Open Connections. Find the installation in Enrolled installations for the repository and read its Last sync, Unsent and Offline cells.
What you see. Offline reads Silent for 6 days, Unsent reads the transcript files and bytes waiting for this repository with the oldest age, and the Developer and device cell reads Cannot support an investigation: health report stale.
What it establishes. The developer opens the desktop app, the backlog uploads on the next cycles, and a Re-run of the check passes once the installation reports again.
Before you start
- Supported versions
- Read against origin/main at ddbee985c, after the v0.3.2 release. The coverage view, the case matrix and the required check are on main; installations must run a desktop build that reports evidence coverage, or Connections reads evidence coverage not reported (update RepoOps).
- Where it runs
- Hosted: the repository page, Connections and the case dialog. Desktop: acceptance in Settings and the Transcript delivery row of Runtime health. The desktop case drawer shows the matrix read-only; retrieval runs from the hosted case.
- Permissions
- Publishing, pausing, exceptions, coverage and retrieval need the owner or admin role; both roles can do everything here. A member sees Managed installation and evidence coverage is shown to team owners and admins on Connections and restricted rows in the matrix. Accepting needs an interactive desktop binding of at least member role; a fleet token is refused.
- Connections
- The GitHub App installed on the repository, a bound desktop installation per developer, and hosted encrypted storage provisioned; without storage the repository card says acceptance cannot deliver transcripts yet. The check needs the GitHub App subscribed to pull request events, and to Check run events for Re-run. The access restriction needs the installation to grant Administration: Read and write on the repository.
- Plan
- Every managed route requires a paid hosted plan (Solo Hosted and above). On a lower plan the retrieve button reads Requesting installation evidence needs the hosted plan.
Configure it
- Publish the required policy on the repository page.
Set New transcript retention (days) and press Publish required policy. The status line reads Policy version N: acceptance required. The table Repository installation acceptance then lists each installation as Current policy not accepted until its developer accepts.
- Each developer accepts on their own installation.
On the desktop app, Settings, Managed GitHub repositories: pick the GitHub repository, tick the acceptance box and press Accept this policy. The line reads Policy accepted. Evidence verification is pending. Uploads start on the next capture cycle.
- Read coverage on Connections.
Every enrolled installation gets one row. A row that cannot help an investigation says why, in the words the check uses: capture not running, delivery blocked, no capture adapter for aider, evidence backlog since a time more than 24 hours ago. Required developers without a current installation are counted above the table, and Today lists each one as a coverage failure.
- Retrieve what a case is missing.
On a hosted case, Retrieve missing evidence asks at most eight linked installations for the case's sessions. The same queue is reachable from Captured transcripts on the repository card, where Request captured evidence names an exact session ID and a source.
- Make the check a merge gate.
RepoOps posts the RepoOps managed evidence check run on every pull request of a managed repository. To block merges, add it as a required status check in the repository's branch protection yourself; RepoOps does not change branch protection.
- Optionally, restrict repository access to enrolled developers.
Under Repository access, turn the option on, choose Remove direct access or Downgrade to read and a grace period, and press Save access settings. Press Preview changes (dry run), read the list, tick the confirmation and press Apply. Apply automatically, with a daily limit, runs once an hour without a fresh confirmation; leave it off to confirm every change yourself.
- Add exceptions where a commit cannot carry evidence.
Under Required check on the repository card, add a Bot login exception (up to 365 days) or an Emergency, one pull request exception (up to 7 days) with a reason of 10 to 500 characters. Without one, bot commits fail the check.
| Setting | Where | A sensible choice | Why it matters |
|---|---|---|---|
New transcript retention (days) | the Managed installations card on /team/repos/<repo> | 30 (the default), 7 to 365 | Hosted snapshots expire this many days after upload and a daily sweep removes them; the manifest stays and reads Retention expired; the manifest remains. Records stored before a change keep their expiry. |
Case evidence hold (days past the window) | the Managed installations card on /team/repos/<repo> | 30 (the default), 0 to 365 minus the retention | Becomes the hold clause in the policy each installation accepts. A hold placed on the team Settings page for an open case keeps a snapshot this many days past its window at most, and never more than 365 days from upload. It reaches only snapshots uploaded under a policy version that carries the clause, so evidence from an installation that accepted an earlier version keeps its window until that installation accepts the new one. With 0 the policy has no clause and a hold does not reach this repository. |
State | Publish required policy or Pause managed disclosure | required while the team investigates this repository | A paused policy stops uploads and requests, and the check posts a neutral result titled Managed policy paused. |
Captured source | the Request installation evidence form | All supported sources, Claude Code or Codex | A case retrieval always asks for all supported sources. |
Exception kind and days | Required check on the repository card | Bot login for automation accounts; Emergency, one pull request for a single hotfix; Emergency access, one person (up to 30 days) for someone who must keep repository access | Each exception is written to the audit record and can be revoked. The check ignores emergency access exceptions; the access restriction honors them. |
Grace period (days) | Repository access on the repository card | 7 (the default), 0 to 30 | Counted from the later of the policy's publication and the first hourly access sweep that saw the person, so a new collaborator has time to enroll. |
Apply automatically and Daily limit | Repository access on the repository card | off (the default); when on, 1 to 20 changes in any 24 hours | The hourly run acts as the owner or admin who turned it on and stops if that person loses the role. |
What you should see
An installation that is fully covered
Configuration. A required policy, one developer who accepted it, capturing Claude Code sessions, online.
Expect. Connections shows the installation with Captured: Claude Code, a recent Last verified receipt, Offline reading Reporting, and snapshots under Retained cloud evidence. The developer's pull request check reads Managed evidence present.
Verify. Every cell names daemon health report, managed evidence receipts or managed evidence storage with a time. On the desktop, Runtime health's Transcript delivery row counts verified captured snapshots.
A request to an offline installation
Configuration. The case's session ran on a laptop that is shut.
Expect. The request reads queued, and the Owner requests cell reads 1 queued. If the laptop does not poll within 72 hours the request reads expired.
Verify. When the laptop wakes, its next capture cycle claims the request, the state moves to collecting and then received or partial, and the case matrix updates.
A commit from a session that was never uploaded
Configuration. A commit carries a Session-Id trailer whose session has no verified snapshot.
Expect. The check title reads 1 commits not covered by managed evidence, with the commit named and the reason the commit names a session with no verified evidence snapshot yet.
Verify. Once the snapshot is verified, press Re-run on the check (it needs the Check run subscription) or push again.
Data and cost
- What is captured
- The complete captured Claude Code or Codex session files assigned to the managed repository, uploaded in chunks and verified by hash. A source that mixes another repository or session is held locally and reads Source includes another repository or session; held locally. Provider-encrypted content stays encrypted by its provider.
- Who can see it
- Repository-authorized owners and admins of the team can read the stored snapshots and request more. Members cannot. Reading opens a redacted preview by default, with credentials, tokens, keys and emails masked and the masked spans and withheld bytes declared; the original is a separate audited read, and search reads only the preview. Unrelated repositories and personal chats are outside the policy, and personal transcript grants on data requests are a separate flow.
- How long it is kept
- Hosted snapshots expire by the policy's retention. A case evidence hold keeps a snapshot past that only under a policy version with the hold clause, for an open case, up to the clause's days; placing and releasing one is written to Managed evidence audit, and a released or ended hold returns the snapshot to its window. On the desktop, the transcript sweep keeps any session whose managed upload is not verified; if the upload state cannot be read, it removes nothing. RepoOps never deletes the tools' own session folders.
- What leaves the machine
- Uploads go from the installation to the hosted service over its authenticated outbound connection. There is no inbound port and no remote shell: a request is a row the installation reads when it polls.
- What it costs
- No model call. Storage counts against the hosted team, and each verified snapshot keeps a redacted preview beside its original, so stored bytes are roughly twice the captured bytes. Owner preview reads, original reads, requests, claims, results, exceptions and access changes each write an audit row; the repository page lists them under Managed evidence audit.
When the result differs
| Symptom | Likely cause | Next action |
|---|---|---|
| A row reads evidence coverage not reported (update RepoOps). | The installation runs a desktop build that does not report evidence coverage. | Update the desktop app on that machine. |
| The repository card says encrypted transcript storage is unavailable. | The hosted store is not provisioned for this deployment. | Ask the operator to provision hosted encrypted storage; acceptance cannot deliver transcripts until then. |
| A request stays queued. | The installation has not polled: it is offline, its capture service is not running, or it is busy on another request. | Read Offline and Last sync on Connections. The request expires after 72 hours; queue it again once the installation reports. |
| A request reads policy-changed, policy-paused or scope-unverified. | The policy moved after the request was made, or the installation could not prove the session belongs to this repository. | Accept the current policy on the installation, then request again. These states print as raw names in the request list. |
| A snapshot reads The redacted preview is still being prepared. | The server builds the preview a few chunks at a time as the upload arrives; a large snapshot can finish uploading before its preview does. | Press Read preview or Retry page: each read continues the build. Read original is available meanwhile and is recorded in the audit trail. |
| Diagnostics reads unsupported in every case. | No diagnostics family is collected yet. | Read installation health on Connections or on Runtime health at /team/runtime-health. |
| Re-run on the check does nothing. | The GitHub App is not subscribed to Check run events. | Push a new commit, or ask the operator to add the subscription (LDG-0953). |
| Restrict repository access to enrolled developers is disabled. | The GitHub App installation lacks Administration: Read and write on the repository, or RepoOps could not read its permissions. | Open the linked installation settings on GitHub and approve the permission. If GitHub does not offer it, the RepoOps App has not requested it yet; ask the operator to add it to the App. |
| A person the dry run lists as not enforceable keeps access. | They reach the repository through a team or the organization's base role, not a direct grant. | Change the team or base role in GitHub; RepoOps does not modify teams or organization settings. |
| Required developers reads not reported. | No GitHub collaborator observation is stored yet. | Wait for the hourly access sweep on a paid team with the GitHub App installed. |
- Disable
- Pause managed disclosure on the repository page. There is no per-installation opt-out while a policy is required.
- Roll back
- Publish a new policy version to change retention, the hold allowance or scope; every installation accepts again. Stored snapshots keep the expiry they were given and the hold terms of the version they were uploaded under. A desktop build that does not know the hold clause cannot deliver under a policy that carries it, and reads as not delivering until it updates.
- Revoke access
- Removing a developer's repository access or revoking the installation's enrollment ends its eligibility; the acceptance table reads Repository access removed or Enrollment revoked. A direct access change RepoOps made is undone with Restore previous access in the Repository access changes table.
- Delete
- Not provided as a button. Hosted snapshots are deleted by the retention sweep when they expire; the manifest remains.
Related tasks
Maintenance evidence
- Feature id
managed-installations(spine leaffirst-run)- Owner
- Managed enrollment (LDG-0952, LDG-0957, LDG-0969, LDG-0970). Guide: LDG-0981.
- Supported product version
- RepoOps main at ddbee985c (after v0.3.2)
- Last verified
- 2026-09-26, read against origin/main at ddbee985c; labels read from website/components/managed-repository-panel.tsx, managed-coverage.tsx, case-coverage.tsx, evidence-requests.tsx, managed-check-exceptions.tsx and public/settings.html; limits read from website/lib/raw-fidelity/requests.ts, website/lib/managed-compliance.ts and lib/raw-fidelity/chunk-tick.mjs.
- Example fixtures
- Inline in the tests: website/lib/managed-coverage.db.test.ts, website/components/managed-coverage.test.tsx, website/lib/managed-compliance.test.ts, website/app/api/github/webhook/route.managed-evidence.test.ts, website/lib/raw-fidelity/requests.db.test.ts, website/lib/raw-fidelity/case-coverage.db.test.ts, lib/raw-fidelity/chunk-tick.test.mjs, lib/raw-fidelity/request-delivery.test.mjs and lib/record-family-retention.test.mjs.
- Source references
website/components/managed-repository-panel.tsx,website/lib/managed-repository.ts,public/settings.html,public/lib/managed-repository-setup.js,lib/raw-fidelity/chunk-tick.mjs,lib/raw-fidelity/request-delivery.mjs,website/lib/managed-coverage.ts,website/components/managed-coverage.tsx,website/lib/managed-compliance.ts,website/lib/raw-fidelity/requests.ts,website/components/case-coverage.tsx,website/lib/raw-fidelity/case-coverage.ts,website/lib/github/pr-managed-evidence.ts,website/components/managed-access-enforcement.tsx,website/lib/managed-access.ts,website/lib/managed-access-store.ts,website/lib/github/repository-admin.ts,lib/record-family-retention.mjs- Documentation review
- Written by the authoring agent against the code; independent review not yet recorded.
- Video review
- Narrated story rendered and published 2026-09-26; six frames, captions and transcript reviewed by the authoring agent, not an independent reviewer. The story is a labeled synthetic explanation, not a recording of a packaged device.
Last updated