# Joining an existing project

You're the second (or nth) developer joining a project that's already been DevAudit-onboarded by the first dev (the project's "operator"). This guide is for you. **Don't run `devaudit install`** — that's the operator's command and it touches the team's shared CI configuration. Use `devaudit join` instead, or just the verify commands below if you already trust the synced framework files.

---

## TL;DR — the five commands

```bash
npm install -g @metasession.co/devaudit-cli            # one-time, all projects
# Issue a personal PAT at https://devaudit.ai/settings/tokens
devaudit auth login                                    # paste mctok_…
gh auth login                                          # if not already
devaudit doctor                                        # node ≥22, git, gh, jq, curl
devaudit status .                                      # framework files present?
devaudit join .                                        # re-sync templates + git hooks (optional)
```

If `devaudit doctor` and `devaudit status .` are both green, you can skip `devaudit join` — the synced framework files (`SDLC/`, `compliance/`, `scripts/`, `.husky/`, `.github/workflows/`, AI rule files) are already in the repo from the first dev's onboarding commit, and you'll get them on `git clone`. Run `join` after the next `devaudit update` from the operator, or whenever your local templates feel out of date.

> **One-liner you'll want to remember:** *`install` creates / rotates / re-applies team configuration; `join` does not.* The CLI auto-detects this scenario as a safety net, but `join` is the explicit second-dev command.

---

## What's already in the repo (and why)

When you `git clone`, you've already got everything the framework synced into the project on first install:

| Path | What it is | Who owns it |
| --- | --- | --- |
| `sdlc-config.json` | Project-wide config (stack, host, slug, runtime, UAT, approval mode, e2e knobs, …) | Team — committed by the operator |
| `SDLC/*.md` | Stage walkthroughs (0-project-setup, 1-plan-requirement, …) — synced from DevAudit-Installer | Team — refreshed by `devaudit update` |
| `compliance/RTM.md`, `compliance/risk-register.md`, … | Compliance artefacts | Team — appended by tracked work |
| `scripts/*.sh` | Helpers (`upload-evidence.sh`, `close-out-release.sh`, `validate-commits.sh`, …) | Team — synced from DevAudit-Installer |
| `.husky/`, `.github/workflows/*.yml` | Git hooks + CI gates | Team — generated by the operator's onboarding install |
| `AGENTS.md`, `.cursorrules`, `.windsurfrules`, `GEMINI.md`, `INSTRUCTIONS.md`, `CLAUDE.md` | AI rule files | Team — synced |
| `.claude/skills/` | The `sdlc-implementer` + `e2e-test-engineer` Claude Code skills | Team — synced |

Your job is to wire up the **local** half (the bits per-developer):

- The CLI globally on your machine.
- Your personal PAT in `~/.config/devaudit/auth.json` (set by `devaudit auth login`).
- `gh` CLI authenticated against the project's GitHub repo.

That's it. You **do not** create a new portal project, issue new API keys, or write new GitHub repo secrets — those belong to the operator.

---

## Step-by-step

### 1. Install the CLI globally

```bash
npm install -g @metasession.co/devaudit-cli
devaudit --version   # ≥ 0.1.23 — earlier versions don't have the dev-mode safety net
```

#### Checking for updates

The CLI is distributed via **npm** — not GitHub releases. To check your current version against the latest published on npm:

```bash
# Your installed version:
devaudit --version

# Latest version on npm:
npm view @metasession.co/devaudit-cli version

# All published versions (if you need to pin to a specific one):
npm view @metasession.co/devaudit-cli versions --json
```

If your installed version is behind `npm view` output, upgrade:

```bash
npm install -g @metasession.co/devaudit-cli@latest
devaudit --version   # confirm the bump
```

The `npx @metasession.co/devaudit-cli@latest` invocation always pulls the latest npm version on first run — no global install needed. Use this for CI or one-off commands to guarantee you're on the current release.

### 2. Issue + paste a personal access token

Visit `https://devaudit.ai/settings/tokens`, create a token (it starts with `mctok_`), then:

```bash
devaudit auth login
# Paste the token when prompted. Stored at ~/.config/devaudit/auth.json (mode 0600).
```

Verify:

```bash
devaudit auth status
#   token source: ~/.config/devaudit/auth.json
#   portal:       https://devaudit.ai
#   accessible projects: <slug>, <slug>, …
```

### 3. Authenticate `gh` against GitHub

```bash
gh auth status   # already authenticated?
# If not:
gh auth login    # GitHub.com → HTTPS → with web browser
```

### 4. Verify your local environment

```bash
devaudit doctor
#   ✓ node     v22.x.x (require ≥22)
#   ✓ git      git version 2.x.x
#   ✓ gh       gh version 2.x.x
#   ✓ jq       jq-1.x
#   ✓ curl     curl 8.x.x
#   ✓ releases <N> pending ticket(s); none released on the portal
```

### 5. Verify the project is SDLC-ready

```bash
devaudit status .
#   Project:    <slug>
#   Stack:      node / python
#   Host:       railway
#   …
#   ✓ INSTRUCTIONS.md, AGENTS.md, CLAUDE.md, .cursorrules, …
```

If any of the framework files are missing, the operator hasn't completed onboarding yet (or your clone is behind `main` — `git pull`). Ask them to run `devaudit update`.

### 6. (Optional) `devaudit join .` to refresh local-only state

```bash
devaudit join .
# Runs auth probe, stack detect, hook bootstrap, template sync.
# Skips: write sdlc-config, issue API key, set GH secrets, apply branch protection.
```

The output will tell you which steps it skipped and why (developer mode). If `git status` is clean after the join, your local state matches the team — you're done. If templates drift (occasionally on a new CLI version), commit the drift on a `chore:` branch and open a PR.

You can skip this step entirely if the synced templates from `git clone` are already current — `devaudit status .` will tell you.

---

## The token model

Two distinct credentials exist; conflating them is what causes the silent-CI-token rotation bug this guide exists to prevent.

| Credential | Format | Where it lives | Who it identifies | Used by |
| --- | --- | --- | --- | --- |
| **Personal PAT** | `mctok_…` | `~/.config/devaudit/auth.json` (per developer) | You (the user) | Your local CLI commands |
| **Project API key** | `dak_…` | Repo secret `DEVAUDIT_API_KEY` | The project | CI's `devaudit push` calls |
| **Operator's PAT** | `mctok_…` | Repo secret `DEVAUDIT_USER_TOKEN` | The operator (singular) | CI's DevAudit portal calls that need human attribution (release submit / approval flows) |
| **GitHub workflow token** | `${{ github.token }}` | Issued automatically per workflow run | The GitHub Actions workflow | CI's GitHub repo mutations (checkout, branch push, PR, issue, comment, label, check-run updates) |

**Never paste your personal PAT into a repo secret.** Repo `DEVAUDIT_USER_TOKEN` is operator-owned and is not the default GitHub auth path for workflow repo mutations. CI portal mutations are attributed to whoever's PAT is there — if it's yours, your name shows up against every release the team ships, and the moment your PAT expires CI portal actions break. Rotation belongs to the operator: `devaudit install --force-team-config` on their machine.

If `devaudit auth status` shows the wrong user, run `devaudit auth logout && devaudit auth login` and paste the right PAT.

---

## Why not `devaudit install`

`install` is the **operator's** command. It does eleven steps including:
- writing `sdlc-config.json`,
- creating the portal project (if absent),
- issuing a new project API key (if absent),
- writing four repo secrets (including `DEVAUDIT_USER_TOKEN` to whoever ran the command),
- applying branch protection rules.

A second dev running it silently rotates the team's `DEVAUDIT_USER_TOKEN` repo secret to their personal PAT — which (a) breaks CI attribution and (b) ties CI's expiry to your PAT lifetime.

**As of 0.1.23 the CLI detects this scenario and routes to developer mode automatically** (skipping the destructive steps), but `devaudit join` is the explicit, intent-correct command. If you ran `install` and want to verify the safety net engaged, look at the report's "11/11 Done" line — `Done (developer mode)` means it did; `Done` (no suffix) means you were in operator mode (either a fresh project, the safety net didn't engage, or `--force-team-config` was passed).

---

## Local-vs-CI parity

The synced CI gates expect a specific environment. Here's what you need locally if you're running them against the same project:

| Surface | CI | Local (your machine) |
| --- | --- | --- |
| Personal identity | `secrets.DEVAUDIT_USER_TOKEN` (operator's, portal-only) | `~/.config/devaudit/auth.json` (yours) — `devaudit auth login` |
| Project API key | `secrets.DEVAUDIT_API_KEY` | Usually unset locally — only needed if you're testing `devaudit push` against the live portal; ask the operator if you need to debug it |
| Portal URL | `vars.DEVAUDIT_BASE_URL` | `~/.config/devaudit/auth.json` (set by `auth login`) or `$DEVAUDIT_BASE_URL` env |
| GitHub auth | `${{ github.token }}` (auto, repo mutations) | `gh auth login` |
| Node | matrix-pinned to project's `node_version` | nvm / volta / whatever — `devaudit doctor` checks ≥ 22 |
| `jq` / `curl` | always present on GH runners | install via package manager — `devaudit doctor` flags absence |

For everything else (DB migrations, env files, `npm install`), the consumer's `README.md` is the source of truth.

---

## Troubleshooting

| Symptom | Cause | Fix |
| --- | --- | --- |
| `devaudit status` reports missing framework files | Local clone is behind `main`, or the operator hasn't run a recent `devaudit update` | `git pull origin develop` first; if still missing, ping the operator |
| `devaudit auth status` says "token rejected" | PAT expired, was revoked, or you typed it wrong | Issue a fresh PAT at `/settings/tokens` and re-run `devaudit auth login` |
| `devaudit doctor` flags missing tool | The matching binary isn't on PATH | Install via your package manager (`brew install gh`, `apt install jq`, etc.) |
| "I ran `devaudit install` and now CI is broken" | The 0.1.23+ safety net should have caught this, but if you're on an older CLI version, `DEVAUDIT_USER_TOKEN` may have been rotated to your PAT | Ask the operator to run `devaudit install --force-team-config` from their machine — that re-writes `DEVAUDIT_USER_TOKEN` from their PAT |
| `devaudit join` exits 7 saying "sdlc-config.json missing" | The project hasn't been onboarded yet (you're the first dev) | This is the operator's job — run `devaudit install <path>` |

---

## What to do next

The framework's per-stage walkthrough is in `SDLC/implementing-an-sdlc-issue.md`. For day-to-day implementation work, run the `sdlc-implementer` skill from your AI assistant (Claude Code, Windsurf, Cursor — it's already synced into `.claude/skills/`):

```text
> Implement issue #N under the SDLC.
```

For the operator-side onboarding flow (your reference if you ever become the operator on a new project), see [`docs/onboarding.md`](https://github.com/metasession-dev/DevAudit-Installer/blob/main/docs/onboarding.md) in DevAudit-Installer.
