# KB Repository Access Grants

> Canonical path: `specs/kb/kb-repository-access-grants.md`
> Status: draft product-engineering spec
> Scope: user journeys and support model for granting repository access from inside the Knowledge Base product.

## 1. Purpose

Workspace-visible Knowledge Bases and AGS repositories use different permission
systems. A workspace member may be allowed to open a KB, ask questions, and read
KB metadata while still being unable to open the private repository that backs a
source. The KB product must provide an in-context way for KB managers to grant,
repair, and understand repository access without asking users to leave the KB
surface and manage raw AGS collaborators manually.

This spec defines the product journey and technical support model for
KB-controlled repository access defaults and repository-row overrides.

## 2. Baseline To Preserve

The KB product already has these durable boundaries:

- `knowledge_base_grants` controls KB product roles for humans and agents.
- Workspace membership gives humans a configurable public KB default role of
  `view`, `edit`, or `manage`; legacy `none` defaults resolve to `view`.
- Explicit KB roles (`owner`, `manage`, `edit`, `view`, `none`) control
  metadata, source, and grant-management operations.
- Repository mappings live in `resource_repositories`; repository identity must
  not be copied back onto `knowledge_base_sources`.
- AGS owns repository collaborators and repository permissions.
- Creating a repository-backed source records durable repository access intent
  for the initiating human; reconciliation, not an implicit permanent
  collaborator side effect, materializes the AGS permission.
- Granting an agent KB access materializes read collaborator access for source
  repositories so retrieval and replay can use repository-backed content.

The missing product behavior is human post-creation repository access management
for users who can view a KB but cannot read, write, or manage the private
repositories behind its sources.

## 3. Product Principles

1. **One product place to fix access**: When a source cannot be opened because
   the backing repository is private, the KB surface should explain the
   repository-access problem and route managers to the KB permissions/access
   panel.
2. **KB roles and repository permissions stay distinct**: KB roles decide
   product operations. Repository access grants only materialize AGS collaborator
   permissions needed for repository-backed source tabs.
3. **Per-repository-row override beats inherited defaults**: A human grant has a
   KB-level repository access default, and each `(source_id, repo_role)` row may
   override that default. The repository-row override is the effective product
   intent when present.
4. **MeshX owns intent; AGS owns enforcement**: MeshX records the KB-owned intent
   to grant repository access and reconciles it into AGS collaborators. AGS
   remains the runtime authority for repository operations.
5. **No hidden repository exposure by default**: Human grants target repositories
   that are user-visible or product-route-visible from source detail. The
   `insights` repository is system-managed backend storage and is independently
   configurable from source repository access; it remains closed unless an
   explicit repository intent grants it for a specific subject and source.
6. **Idempotent and repairable**: Grant, revoke, and source-creation
   reconciliation must be retryable. Managers need to see blocked grant state and
   repair it without editing repository rows manually.
7. **Explicit management is allowed**: Repository `manage` maps to AGS `admin`
   for the selected source or `insights` repository. It should be available only
   to KB `owner`/`manage` actors and should be presented as repository
   management, not as KB ownership.

## 4. Repository Access Profiles

A human KB grant can have a KB-level repository access profile and optional
repository-row overrides.

| Profile  | AGS permission                 | Intended user capability                                                                                                            |
| -------- | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- |
| `none`   | no KB-owned collaborator grant | User can still use KB product reads allowed by KB policy, but repository-backed tabs may show an access-required state.             |
| `read`   | `read`                         | Browse files, wiki, issues, pull requests, labels, releases, insights, and source activity where AGS read permission is sufficient. |
| `write`  | `write`                        | Maintain source or insights repository content and work items where repository write permission is required.                        |
| `manage` | `admin`                        | Manage the mapped repository in AGS, including settings-like operations exposed by the source detail surface.                       |

Default recommendations:

- KB `view` -> repository `read` when a manager chooses to grant repository
  access.
- KB `edit` -> repository `write` when the member is expected to maintain
  sources.
- KB `manage` / `owner` -> repository `write` by default; the manager may choose
  repository `manage` for subjects who need AGS admin-level source repository
  operations.
- KB `none` -> repository `none` unless the manager is temporarily preserving an
  existing explicit repository access intent for later re-enablement.
- Agents remain limited to repository `read` unless a later agent-maintenance
  spec expands agent capabilities.

The UI may present these as labels such as “No repository access”, “Can browse
source repositories”, “Can maintain source repositories”, and “Can manage source
repositories”. In Chinese product copy, the equivalent labels are “不可访问”,
“读”, “读写”, and “管理”.

Eligible repositories are the `resource_repositories` rows for the KB sources
that are either user-visible or product-route-visible from source detail. The
user-visible source repository (`canonical` in default mode, `mirror` in mirror
mode) is eligible. The `insights` repository is system-managed backend storage
and is eligible only when an explicit repository intent names the `insights`
role; it must not inherit access from the source repository's user-visible flag
or AGS visibility. KB-created source repositories are private by default, and
source creation does not expose a client-selected public/private visibility
setting.

## 5. Inheritance And Override Semantics

For an explicit human KB grant, the effective repository access profile for a
repository row is resolved from weakest to strongest:

1. The grant's KB-level repository access profile.
2. A workspace repository access profile, when a deployment/product profile
   explicitly materializes one for the subject and repository role.
3. An explicit override for the grant, source id, and repo role.
4. For agent subjects, the agent KB grant or agent binding policy, which may
   independently choose source, `insights`, or both as read-only materialization
   targets.

The override profile can be `none`, `read`, `write`, or `manage`. `none` is an
explicit repository-row deny for KB-owned repository materialization. Deleting
the override restores inheritance from the weaker precedence level.

Overrides may broaden or narrow the KB-level default. Examples:

- A KB default `read` with one source override `write` lets the member maintain
  only that source repository.
- A KB default `write` with one `insights` override `none` leaves the source
  repository open while closing generated insight storage.
- A KB default `none` with one source override `read` and an `insights` override
  `none` lets the member open only the user-visible source repository.
- A KB default `none` with one `insights` override `read` and a source override
  `none` lets the member open only generated insights while source files remain
  closed.
- A repository-row override `manage` grants AGS `admin` for that mapped
  repository but does not grant KB `manage`.

New repository-backed sources inherit each explicit grant's KB-level repository
access profile until a manager sets a repository-row override for that source
and repository role.

The all-workspace-members KB default never creates bulk AGS repository grants.
Repository access defaults and overrides apply only to explicit human KB grants
and agent KB grants.

## 6. User Journeys

### 6.1 Manager grants repository access while adding a KB member

1. A KB manager opens Knowledge -> Permissions.
2. The manager selects a KB and searches for a workspace member.
3. The manager chooses the KB product role (`none`, `view`, `edit`, or
   `manage`).
4. The panel shows a KB-level repository access selector with a recommended
   default derived from the KB role.
5. The manager optionally expands source repositories and sets per-repository
   role overrides.
6. The manager confirms the grant.
7. MeshX persists the KB role, the KB-level repository access default, and any
   repository-row overrides.
8. MeshX reconciles all eligible repository rows for that KB into AGS
   collaborator grants according to each effective profile.
9. The member can open source, insights, activity, and convergence surfaces for
   repository rows where their effective profile is not `none`.

Success state:

- The member row shows both the KB role and KB-level repository access profile.
- Expanded source rows show inherited default, override value, effective profile,
  and materialization status.
- If all AGS collaborator grants are current, the row shows no warning.

Failure state:

- If AGS grant materialization fails for one or more repositories, the row
  remains visible with a “repository access needs repair” warning and a repair
  action.
- The KB role must not be silently rolled back unless the grant request is
  rejected before persistence. Product access and repository-access
  materialization are distinct facts.

### 6.2 Manager upgrades an existing KB member after an access-required report

1. A workspace member opens a KB source and sees a repository-access-required
   state.
2. The state explains that the KB is visible but the backing repository is
   private for this account.
3. If the member is not a manager, the state offers a non-mutating request path
   such as “Ask a KB manager for repository access”.
4. The manager opens the KB permissions panel from the source state or
   notification.
5. The manager updates either the member's KB-level repository access profile or
   that source/repository-role override from `none` to `read`, `write`, or
   `manage`.
6. MeshX reconciles the affected repository rows and records audit events.
7. The member refreshes or retries the source tab and reaches the
   repository-backed content.

### 6.3 Manager revokes repository access without removing KB visibility

1. A KB manager opens the member row in Knowledge -> Permissions.
2. The manager changes the KB-level repository access profile or a source
   override from `read`/`write`/`manage` to `none` while leaving the KB role as
   `view` or higher.
3. MeshX removes KB-owned AGS collaborator grants for affected source
   repositories where the effective profile becomes `none`.
4. The member can still see the KB and use product reads allowed by KB policy,
   but those repository-backed source tabs show the access-required state if no
   other AGS permission path exists.

Revocation must be scoped to grants that MeshX created for this KB. If the same
AGS collaborator access is required by another KB, Memory, Workflow repository,
direct AGS team, direct AGS owner membership, or manual collaborator grant, the
KB revoke operation must not remove that independent access.

### 6.4 New source is added after members already have repository access

1. A KB editor adds a repository-backed source.
2. MeshX provisions the source repositories and records `resource_repositories`
   mappings.
3. MeshX grants the initiating editor repository access as part of source
   creation.
4. MeshX reconciles existing KB repository access intents for the new source
   repositories using each explicit grant's KB-level repository access profile.
5. Members with inherited or overridden `read`, `write`, or `manage` effective
   profiles can open the new source without a separate manager action.

### 6.5 Agent KB grant remains read-only repository materialization

1. A manager grants an agent access to a KB from the agent-centric or KB-centric
   permissions view.
2. MeshX persists an agent KB `view` grant.
3. MeshX grants the agent read access to eligible source and/or `insights`
   repositories according to the agent materialization policy.
4. The agent can retrieve and cite KB content through MeshX product APIs.
5. The agent still cannot manage KB grants, edit sources, or receive repository
   write/admin access through this flow.

## 7. Product Surface Requirements

### 7.1 KB permissions panel

The KB-centric permissions view should show, for each human member row:

- KB role selector with `none` / “不可访问” as an available value;
- KB-level repository access default;
- summarized repository-row materialization status (`current`, `pending`,
  `blocked`, `not granted`);
- a repair action when materialization is blocked;
- concise help text that KB role and repository access are separate.

The row should be expandable into a source/repository-role matrix with:

- source name and safe repository identity;
- repository role (`canonical`, `mirror`, `source`, `insights`, or another
  mapped role returned by MeshX);
- inherited KB-level repository access default;
- override selector (`inherit`, `none`, `read`, `write`, `manage`);
- effective repository access profile;
- materialization status and repair action.

Changing a KB role must not silently rewrite an existing KB-level repository
access default or source override unless the user explicitly changes those
fields. Creating a new grant may preselect recommended repository values, but
saved repository access intent is independent from saved KB role.

The agent section should continue to show agent KB availability and may show read
repository materialization status, but it should not expose write/admin
repository choices for agents. Stale agent rows whose target agent no longer
exists should be filtered out or lazily pruned during permission reads, so the UI
never presents them as current grant targets.

### 7.2 Self-demotion confirmations

When the acting user is editing their own effective access, the UI must require a
confirmation before saving any change that narrows access, including:

- lowering their KB role;
- setting their explicit KB role to `none`;
- lowering their KB-level repository access default;
- adding or changing a repository-row override that lowers the effective
  repository permission for that source and repository role;
- deleting an override when the inherited default is lower than the previous
  effective profile.

The confirmation should explain what the user may lose access to and should be
required even when the user still has other administrative paths outside the KB
product. It must mention KB product visibility, source maintenance, grant
management, and KB-owned AGS repository materialization for source and
`insights` repository rows. Confirmed submissions carry an explicit confirmation
flag; browser-facing server routes must reject unconfirmed self-demotion
attempts defensively so KB, Memory, and Skill permission changes use the same
contract.

### 7.3 Source access-required state

When a user can view the KB but the backing source repository returns
forbidden/not-found for that account, the source detail surface should render a
KB-specific state instead of nested repository 404 pages.

The state should include:

- source name;
- repository identity when safe to reveal through the KB source mapping;
- explanation that KB visibility does not imply private repository access;
- action for managers to open the permissions/access panel for that KB/member;
- action for non-managers to request access or identify who can grant it.

### 7.4 Audit and activity

KB audit events should record:

- KB-level repository access profile grant/update/revoke intent;
- repository-row override create/update/delete intent;
- reconciliation success or blocked status per subject and source/repository
  role;
- manual repair attempts.

Audit text should avoid leaking repository names to users who cannot view the KB.

## 8. API And Storage Support Model

### 8.1 MeshX API

The first implementation can extend the existing permissions API rather than
creating a separate top-level product:

- `GET /api/v1/workspaces/:workspaceId/kb/{kb_id}/permissions` returns KB roles, KB-level repository
  access profiles, repository-row overrides, effective profiles, and
  materialization status for each explicit human grant.
- `POST /api/v1/workspaces/:workspaceId/kb/{kb_id}/permissions/grants` accepts optional KB-level
  repository access profile for human subjects and optional repository-row
  overrides.
- `PATCH /api/v1/workspaces/:workspaceId/kb/{kb_id}/permissions/grants/{grant_id}` updates KB role and
  KB-level repository access profile together or independently.
- `PATCH /api/v1/workspaces/:workspaceId/kb/{kb_id}/permissions/grants/{grant_id}/repository-overrides`
  upserts or clears repository-row overrides for that grant.
- `POST /api/v1/workspaces/:workspaceId/kb/{kb_id}/permissions/grants/{grant_id}/repository-access/reconcile`
  retries blocked materialization for all effective repository-row profiles
  on that grant.

The override mutation payload should identify the source repository row by
`sourceId` and `repoRole`, then set `repositoryAccessProfile` to one of `none`,
`read`, `write`, `manage`, or `null`. `null` means clear the override and restore
inheritance from the weaker precedence level.

Example override mutation:

```json
{
  "items": [
    {
      "sourceId": "src_...",
      "repoRole": "source",
      "repositoryAccessProfile": "none"
    },
    {
      "sourceId": "src_...",
      "repoRole": "insights",
      "repositoryAccessProfile": "read"
    }
  ]
}
```

Responses should return the updated permission summary, including effective
profiles and materialization status, so clients do not need to recompute
inheritance.

### 8.2 Product intent storage

`knowledge_base_grants.repository_access_profile` remains the KB-level default
for explicit human grants.

Repository-row overrides should be stored in a product-intent table separate from
the materialization ledger. A suggested model is
`knowledge_base_source_repository_access_overrides` with these concepts:

- id;
- workspace id;
- knowledge base id;
- grant id;
- source id;
- repository role;
- subject type and subject id copied from the grant for auditing and bounded
  queries;
- repository access profile (`none`, `read`, `write`, `manage`);
- actor ids and timestamps for create/update/delete.

The table should enforce one active override per `(workspace_id,
knowledge_base_id, grant_id, source_id, repo_role)` and should be deleted or
marked inactive when the parent grant or source is deleted.

The override table is source of truth for product configuration. It must not be
reconstructed from the AGS collaborator state or from the materialization ledger.

### 8.3 Materialization ledger

MeshX needs a durable ledger for repository collaborator grants that it owns. The
ledger should be generic enough for KB, Memory, and Workflow repository-backed
resources, but the first user journey is KB-owned.

Required ledger concepts:

- workspace id;
- resource type and resource id;
- repository role;
- repository full name or AGS repository id from `resource_repositories`;
- subject type (`user` or `agent`) and subject id;
- requested AGS permission (`read`, `write`, or `admin`);
- source of intent (for KB, the KB grant id and effective repository access
  profile);
- materialization status and last error;
- timestamps and actor ids for create/update/reconcile/revoke.

The ledger is not a replacement for `knowledge_base_grants` or repository-row
overrides and does not grant KB product visibility by itself. It exists so MeshX
can reconcile, repair, and safely revoke AGS collaborator rows that MeshX
created.

### 8.4 AGS integration

The embedded AGS bridge must support idempotent operations for trusted host
decisions:

- grant repository collaborator with `read`, `write`, or `admin` permission;
- revoke repository collaborator only when the caller owns the materialized grant
  being removed;
- optionally list or check collaborator permission for reconciliation status.

The bridge must continue to resolve AgentTeam users and agents into AGS identities
through the existing identity mapping. KB code should not construct AGS
usernames from display names or repository naming conventions.

### 8.5 Reconciliation rules

MeshX reconciles repository access when:

- a human KB-level repository access profile is granted, updated, or revoked;
- a human repository-row override is created, updated, cleared, or deleted;
- an agent KB grant is added or removed;
- a new source repository mapping is created;
- a manager manually retries a blocked grant;
- a background repair job detects stale ledger rows.

Reconciliation must be idempotent:

- Re-granting the same permission is success.
- Upgrading `read` to `write` or `manage` updates AGS permission.
- Upgrading `write` to `manage` updates AGS permission to `admin`.
- Downgrading `manage` to `write`/`read`, or `write` to `read`, updates only the
  KB-owned collaborator grant and must not remove stronger independent access.
- Revoking removes only the KB-owned materialization when no other MeshX ledger
  row or AGS-native ownership path requires it.

Effective repository access is computed per `(source_id, repo_role)` before
ledger reconciliation:

- `none` means no desired KB-owned collaborator grant for that repository row;
- `read` maps to AGS `read`;
- `write` maps to AGS `write`;
- `manage` maps to AGS `admin`.

When multiple MeshX intents target the same subject and repository, the final AGS
permission must be at least the strongest active desired permission across those
intents. Revoking or downgrading one KB intent must not remove access still
required by another active intent. Permission rank is `none` < `read` < `write` <
`admin`.

#### 8.5.1 Two reconciliation primitives

The reconciliation layer exposes two distinct primitives with non-overlapping
responsibilities. Both share the same desired-row contract (effective profile,
override, agent read materialization) so that human and agent grants never fork
into separate code paths.

**Normal reconcile primitive.** Used whenever the desired KB-owned intent
changes. It is the only primitive permitted to revoke obsolete KB-owned ledger
rows.

- Compute desired rows for the grant and the target repository set using the
  shared desired-row contract.
- Upsert each desired row that is missing, blocked, stale, or weaker than the
  desired permission. When a stronger independent materialization already covers
  the same AGS subject and repository (for example, an admin-level grant owned
  by another MeshX intent), use the stronger permission when re-materializing
  via direct update so the AGS side does not lose any pre-existing stronger
  access.
- Revoke KB-owned ledger rows whose repository role is no longer desired by this
  grant. Revocation removes only the KB-owned materialization, never access
  required by another active MeshX intent or AGS-native ownership path.
- Side effects: AGS grant calls (with `AllowExistingDirectUpdate` semantics) and
  AGS revoke calls (only for KB-owned obsolete rows).

**Repair-only primitive.** Used when the desired KB-owned intent is unchanged
but earlier materialization failed or fell behind. It must never revoke and must
never downgrade.

- Compute desired rows for the grant and the target repository set using the
  same shared desired-row contract.
- Filter desired rows down to the subset that needs repair: rows that are
  missing, blocked, non-current, or whose materialized permission is weaker than
  the desired permission.
- Upsert only those repair rows using the same `AllowExistingDirectUpdate`
  stronger-independent-access semantics as normal reconcile.
- Skip rows that are already current at or above the desired permission. Do not
  touch rows for repository roles that are not in the input repository set.
- Side effects: AGS grant calls only. No AGS revoke calls. No ledger-row status
  changes outside the repair set.

Both primitives leave audit trails through the existing creator-profile grant
audit and reconciliation audit paths; failure semantics from section 10 still
apply and must not be swallowed by helper layers.

The previous `SkipRevocation` reconcile-mode switch has been removed. Code paths
that previously used normal reconcile with `SkipRevocation=true` to fake a
backfill now use the repair-only primitive explicitly, so the absence of
revocation is a property of the primitive, not a per-call toggle on the
general-purpose reconcile path.

#### 8.5.2 Source creation reconciliation

Adding a repository-backed source must not require managers to re-open every
existing explicit grant to materialize the new repositories. The after-source-
create flow is owned by a single helper that combines creator provisioning,
KB-wide repair for the new repositories, creator-specific repair for older
repositories, and audit:

1. Ensure the source creator has a durable KB-owned repository access intent
   (upgrade to `read` if their prior effective profile was weaker than `read`,
   preserving their previous profile for audit).
2. Run the repair-only primitive across every explicit grant of the KB, scoped
   to the newly provisioned source repositories. Existing explicit grants with
   non-`none` effective profile pick up the new repositories automatically;
   `none` profiles and `none` overrides produce no grants for the new
   repositories.
3. If the creator has a non-`none` durable repository access intent after
   step 1 — whether that intent pre-existed step 1 or was just upgraded by it —
   run the repair-only primitive for the creator across the previously existing
   source repositories (excluding the just-created source). This heals stale,
   blocked, or under-powered creator rows on older sources regardless of
   whether the creator profile itself changed during this call, without forcing
   a full KB rescan. The trigger is "creator has a durable non-`none` intent",
   not "step 1 just upgraded the profile", so that a creator whose profile was
   already non-`none` but whose older ledger rows fell behind is still healed.
4. When step 1 newly granted or upgraded the creator profile (the ensure-intent
   helper signals this distinct from "creator already had a non-`none`
   profile"), emit the existing creator repository-access-profile audit event
   using the post-step-3 ledger state. Audit is the narrower trigger; the
   repair in step 3 is the broader one.

The helper must:

- Use the repair-only primitive in steps 2 and 3, never normal reconcile. New
  source creation must never revoke existing KB-owned grants on either new or
  older repositories.
- Skip repair rows whose existing materialization is already current at or
  above the desired permission, including rows covered by stronger independent
  access from another MeshX intent.
- Preserve the existing creator profile grant audit and reconciliation audit
  semantics; errors surfaced by the underlying primitives must propagate without
  being swallowed by the helper.

The after-source-create helper is the only entry point that should orchestrate
these four steps together. Background repair jobs that heal stale creator rows
or blocked grants must reuse the repair-only primitive directly rather than
duplicating the creator-backfill branch.

## 9. Authorization Rules

- Only KB `owner` and `manage` users can grant, change, repair, or revoke
  KB-level repository access profiles.
- Only KB `owner` and `manage` users can grant, change, clear, repair, or revoke
  repository-row overrides.
- KB `edit` users can maintain sources but cannot grant repository access to
  other users.
- A non-manager can request repository access but cannot self-grant it.
- Repository `manage` / AGS `admin` granted by a KB does not grant KB `manage`,
  KB `owner`, or permission to mutate KB grants.
- Repository access alone does not grant KB visibility, retrieval access, or
  management access.
- KB product APIs continue to authorize every KB read/retrieval operation through
  MeshX even when AGS repository access exists.

## 10. Failure Semantics

Repository access operations fail closed for repository-backed tabs but should
not corrupt KB product grants.

- Missing `resource_repositories` mapping: show repair-required to managers; do
  not infer repo names.
- AGS identity resolution failure: keep the KB grant and mark repository
  materialization blocked.
- AGS grant/revoke failure: keep ledger status with last error and offer retry.
- Source or insights repository deleted outside MeshX: mark affected
  materializations blocked and surface source repair state for the specific
  repository role.
- Source deleted from the KB: delete or deactivate repository-row overrides
  and revoke KB-owned ledger rows that are no longer desired by any active
  source.
- Subject leaves workspace: KB grants, repository-row overrides, and KB-owned
  repository materializations should be revoked or marked inactive by the same
  membership cleanup path.
- Target agent no longer exists: stale agent grants should not be shown as
  current UI rows and may be lazily pruned during permission reads or cleanup
  jobs.

## 11. Non-goals

- Replacing AGS repository permission checks with KB grants.
- Granting all workspace members AGS repository access just because a KB is
  workspace-visible.
- Implicitly exposing the system-managed `insights` repository through KB roles,
  owner defaults, or source repository access.
- Granting KB product management solely from repository `manage` / AGS `admin`.
- Modeling repository access through channel shares, thread transport, Project
  membership, or repository name conventions.

## 12. Reconciliation Test Checklist

The two primitives in section 8.5 and the source-creation helper in section
8.5.2 must keep the following acceptance scenarios covered by behavioral tests.
Each scenario lists the contract it locks down and the canonical test that
covers it today. New scenarios or contract changes require updating both the
spec and this checklist together.

Tests live in `internal/service/kb/kb_repository_access_test.go` unless
otherwise noted.

### 12.1 New source materializes existing explicit grants

- Contract: When a second repository-backed source is added to a KB that already
  has an explicit human grant with a non-`none` effective profile, the new
  source repositories must be materialized for that grant. Existing materialized
  rows for the first source must remain current. No revokes may be issued
  during this flow.
- Test: `TestKBServiceCreateSourceRepairsNewSourceWithoutRevokingExistingGrantRows`.
- Locks: section 8.5.2 step 2, repair-only primitive never revokes (section
  8.5.1).

### 12.2 Stale or blocked creator rows are repaired

- Contract: Repository access ledger rows left in a blocked, non-current, or
  under-powered state (for example by a previous failed AGS call) must be
  re-materialized to current when the repair-only primitive runs over them. The
  KB-owned ledger row's permission stays at the KB-desired level; AGS side is
  re-granted at the level that satisfies every active intent. This holds both
  when the creator profile was just upgraded and when it was already
  non-`none` before this source was added.
- Tests:
  `TestKBServiceRepairRepositoryAccessUsesStrongerIndependentPermission`
  (blocked KB-owned rows are repaired to current),
  `TestKBServiceCreateSourceRepairsNewSourceWithoutRevokingExistingGrantRows`
  (creator repair path runs without disturbing prior rows), and
  `TestKBServiceCreateSourceBackfillsCreatorRepositoryAccessWhenProfileAlreadyGranted`
  (canonical coverage for section 8.5.2 step 3 broader trigger: creator
  profile was already `write` and legacy source rows were left stale/blocked;
  adding a new source heals the legacy creator rows via the repair-only path
  without requiring a profile change).

### 12.3 Repair-only primitive never revokes

- Contract: Calling the repair-only primitive scoped to a subset of repository
  roles must not revoke KB-owned grants for repository roles outside that
  subset, even when those rows are stale or above the desired permission.
- Test: `TestKBServiceRepairRepositoryAccessDoesNotRevokeRowsOutsideRepairSet`.
- Locks: section 8.5.1 repair-only primitive side effects (no AGS revoke calls).

### 12.4 Stronger independent access is not downgraded

- Contract: When another active MeshX intent (for example an admin-level
  sibling intent) already materializes a stronger AGS permission for the same
  subject and repository, the repair-only primitive must re-materialize using
  the stronger permission via `AllowExistingDirectUpdate`, so the AGS
  collaborator keeps the stronger access. The KB-owned ledger row records the
  KB-desired permission, not the stronger sibling permission.
- Test: `TestKBServiceRepairRepositoryAccessUsesStrongerIndependentPermission`.
- Locks: section 8.5 multi-intent strongest-permission rule and section 8.5.1
  AllowExistingDirectUpdate semantics.

### 12.5 `none` profile and `none` override do not produce grants

- Contract: A grant with KB-level repository access profile `none` produces no
  repair grants and no ledger rows. A grant with a non-`none` KB-level profile
  plus a per-source `none` override excludes only that source's repository role
  from repair; other repository roles under the same grant still receive their
  desired grants.
- Test:
  `TestKBServiceRepairRepositoryAccessRespectsNoneProfileAndOverrides` (subtests
  `profile_none_creates_no_repair_grants` and
  `override_none_excludes_that_source_repository_from_repair`).
- Locks: section 4 profile `none` semantics, section 5 override precedence, and
  section 8.5.1 desired-row contract shared with normal reconcile.

### 12.6 Audit and failure propagation

- Contract: The after-source-create helper must continue to emit the creator
  profile grant audit event when the creator profile is upgraded, and must
  propagate errors from the underlying primitives instead of swallowing them.
- Test: `TestKBServiceAuditsRepositoryAccessProfileAndReconciliation`
  (existing, in the same file) continues to cover creator profile grant audit
  alongside reconciliation audit.
- Locks: section 7.4 audit requirements and section 10 failure semantics.

### 12.7 Adding or changing scenarios

When the contract above changes:

1. Update sections 8.5.1 and 8.5.2 to describe the new primitive or invariant.
2. Add or update the corresponding entry in this checklist with the test name
   that locks the new behavior.
3. Run `go test ./internal/service/kb ./internal/service/resource/repos -run 'RepositoryAccess|CreateSource|SourceRepository' -count=1`
   and `go test ./internal/service/kb -count=1` to confirm the
   behavior tests still pass.
