Workspace Repository Access

Deny-by-default multi-repository authorization and member policy resolution

Workspace Repository Access

AIWG treats filesystem/tool capability and repository authorization as separate things. A writable clone is not automatically authorized for edits, commits, pushes, tracker comments, service actions, or destructive work.

Canonical manifest

The preferred manifest is the workspace root's `.aiwg/aiwg.config`:

{
  "version": "1",
  "providers": ["codex"],
  "installed": {},
  "scripts": {},
  "workspace": {
    "name": "home",
    "root": "~/dev"
  },
  "repos": [
    {
      "name": "aiwg",
      "path": "./aiwg",
      "allowed": ["read", "write", "commit", "push", "issue-comment"]
    },
    {
      "name": "sysops",
      "path": "/srv/ops/sysops",
      "provider": "gitea",
      "allowed": ["read", "issue-comment"],
      "notes": "handoff-only"
    }
  ]
}

Relative member paths resolve from `workspace.root`, or from the repository containing the workspace config when `workspace.root` is absent. Absolute paths may point anywhere on the system.

Each member has its own `<member>/.aiwg/aiwg.config`. That member config—not the workspace root config—controls:

  • `delivery`, including branch mode, default branch, committer, and signing;
  • `remotes.primary`, `remotes.issue_tracker`, and `remotes.ci`;
  • `remotes.tracker_actor`, including `forbid_actors`;
  • issue taxonomy and other repo-local policy.

Remote URLs are read from the member clone, so provider and domain routing is per member. The optional `repos[].provider` field is only a hint for self-hosted domains whose forge type cannot be identified from the URL; a detectable URL takes precedence.

Authorization semantics

The effective permission is an intersection:

1. the target must resolve to a listed workspace member; 2. `repos[].allowed` must contain the operation; 3. the member's own config must permit and correctly route the workflow; 4. repo-local instructions may narrow access further.

Unlisted paths and unlisted actions deny by default, regardless of filesystem writability or which tools are available.

Allowed operations:

  • `read`
  • `write`
  • `commit`
  • `push`
  • `issue-comment`
  • `service-action`
  • `destructive`

External member discovery

An absolute member can be resolved when a command starts from the workspace root or receives that root explicitly. If commands also start directly inside the external member, add a back-reference to the member config:

{
  "workspace": {
    "member_of": "/home/me/dev/workspace-root"
  }
}

`AIWG_WORKSPACE=/home/me/dev/workspace-root` is the explicit process-level alternative. A `member_of` config cannot also declare `repos`.

CLI

aiwg repo-access list
aiwg repo-access status
aiwg repo-access explain --path /srv/ops/sysops
aiwg repo-access check --path /srv/ops/sysops --action issue-comment
aiwg repo-access check --path /srv/ops/sysops --action write

`list` and `status` show each member's resolved provider/domain, delivery mode, tracker route, config path, and drift. `check` exits `0` for allowed, `1` for denied, and `2` for invalid manifests or usage.

Legacy manifest compatibility

Existing YAML manifests remain supported when the nearest workspace config does not declare `repos`:

.aiwg/ops/security/repo-access.manifest.yaml
.aiwg/security/repo-access.manifest.yaml
version: "1"
default_policy: deny
repos:
  - name: project
    path: .
    actions: [read, write, commit, push, issue-comment]

When both formats exist, `.aiwg/aiwg.config` is authoritative. Migrate by copying each YAML `repos[]` entry into the root config, renaming `actions` to `allowed`, adding `workspace.name`, and then removing the YAML file after `aiwg repo-access status` reports the expected members.

Ops workspace compatibility

`aiwg ops` remains an ops-framework specialization. Its registry adapts to the same `workspace`/`repos` shape; when a canonical workspace config is present, ops pushes use each member's configured primary remote/default branch and honor the member's `push` capability. The user-level ops registry is not a second authorization source.

The `respect-repo-access-manifest` rule requires this preflight for all cross-repository operations and mutations.