Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e67932fcc3 |
@@ -1,41 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [v1.1.0] - 2026-07-02
|
||||
|
||||
### Added
|
||||
- Read-only identity and eligibility tooling: `gitea_whoami` authenticated-user lookup (#11), `gitea_get_profile` runtime-profile discovery (#13), and `gitea_check_pr_eligibility` fail-closed PR eligibility checks (#14).
|
||||
- Identity lookup aliases (`gitea_get_authenticated_user` and `gitea_get_current_user`) for common MCP/LLM tool discovery (#9).
|
||||
- Gated PR review actions (`gitea_submit_pr_review`) reusing the eligibility gates (#15).
|
||||
- Gated PR merge workflow (`gitea_merge_pr`) with explicit `MERGE PR <n>` confirmation, head-SHA and changed-file pinning, and self-merge blocking as the only merge path (#16).
|
||||
- Task-scoped Gitea MCP execution profiles: documented profile model (#12) and runtime profiles via environment config with `allowed_operations` (#19).
|
||||
- Audit logging for all mutating MCP actions with execution-profile metadata and secret redaction (#18).
|
||||
- Shared API pagination (`api_get_all`) and hardened failure handling in `gitea_auth.api_request`: request timeouts, clear network/DNS errors, explicit 502/503/504 upstream errors, malformed-JSON handling, and redacted error text (#67).
|
||||
- `scripts/release-tag` SemVer-gated annotated-tag helper (safe-by-default, master-only, tests required) (#50).
|
||||
- Automatic `status:in-progress` release on issue close and PR close/merge (#56, #58).
|
||||
- `LLM-Agent-SHA` opaque agent attribution convention (Phase 0): documentation, handoff/review templates, and negative tests proving the SHA can never bypass self-review/self-merge gates (#86).
|
||||
- macOS `com.apple.provenance` cleanup helper tool and documentation (#3).
|
||||
- `manage_labels.py` refactored into reusable modes (`--create-labels`, `--apply-mapping`, `--add-label`) (#6).
|
||||
|
||||
### Changed
|
||||
- HTTP 429 responses now honor `Retry-After` with jittered exponential backoff (#27).
|
||||
- Read-only list tools (`gitea_list_issues`, `gitea_list_prs`, `gitea_list_labels`) now paginate across pages with bounded page caps (#67).
|
||||
- Automatic `status:in-progress` cleanup on issue/PR close and merge.
|
||||
- Label cleanup now utilizes safe targeted label deletion behavior rather than replacing the entire label set.
|
||||
|
||||
### Documentation
|
||||
- MCP security model and trust-boundary documentation (#8).
|
||||
- Developer testing guidelines (#70).
|
||||
- Jenkins read-only build-status tools design (#72).
|
||||
- Jenkins repo/branch/PR → job mapping design (#77).
|
||||
- Safety and boundary docs updated for Jenkins/GlitchTip: `glitchtip-mcp` boundary, read-only-first policy, mutation gating (#79).
|
||||
- Proposed label taxonomy for Jenkins/GlitchTip workflows (#80).
|
||||
- GlitchTip read-only error/event tools design (#73).
|
||||
- Multi-service MCP profile model extension (#76).
|
||||
|
||||
## [v1.0.1]
|
||||
- Fix Recent Timesheets Remove button text clipping and copy theme/whats_new in build.
|
||||
|
||||
## [v1.0.0]
|
||||
- Initial versioned release.
|
||||
@@ -1,174 +0,0 @@
|
||||
# GlitchTip Read-Only Error/Event Tools — Design Notes
|
||||
|
||||
- **Status:** Design (implementation-ready notes; **no implementation in this repo**)
|
||||
- **Issue:** #73 (umbrella: #75; boundary decision: ADR-0001, #71)
|
||||
- **Related:** #74 (GlitchTip→Gitea filing workflow — composes these read tools),
|
||||
#78 (dedup/linking, child of #74), #76 (per-service profile schema)
|
||||
- **Date:** 2026-07-02
|
||||
|
||||
## 1. Purpose and scope
|
||||
|
||||
Define the minimum **read-only** GlitchTip MCP tool set that lets an LLM answer:
|
||||
*"What unresolved errors does project X have (by environment/release), and what
|
||||
is this specific error?"* — with privacy-safe output suitable for LLM context,
|
||||
issue bodies, and audit logs.
|
||||
|
||||
Strictly read-only, per ADR-0001:
|
||||
|
||||
- **No mutation tools** — no resolving/ignoring/assigning issues, no comment
|
||||
posting, no project/team/key administration, no deletes.
|
||||
- **No automatic GlitchTip→Gitea filing** (that is #74's *orchestrated,
|
||||
explicitly-invoked* workflow; it composes these read tools and Gitea write
|
||||
tools — never one dual-credential server).
|
||||
- **This server never holds Gitea write credentials.**
|
||||
|
||||
## 2. Boundary placement (namespace pending)
|
||||
|
||||
These tools belong to the GlitchTip observability boundary of the MCP Control
|
||||
Plane — `glitchtip-mcp` (ADR-0001's recommendation), `observability-mcp`, or
|
||||
folded into `ops-mcp`. **ADR-0001 open owner decision #2 picks the name; this
|
||||
design does not assume it.** Tool names below use the `glitchtip_` prefix for
|
||||
readability and rename mechanically with the decision.
|
||||
|
||||
Fixed regardless of the name (per `tool-boundaries.md`,
|
||||
`credential-isolation.md`):
|
||||
|
||||
- Own server process, own `.env`, GlitchTip credentials only.
|
||||
- No Gitea, Jenkins, or Ops tokens in this runtime; no GlitchTip token
|
||||
anywhere else.
|
||||
|
||||
## 3. API surface note (Sentry compatibility)
|
||||
|
||||
GlitchTip implements a Sentry-compatible REST API (`/api/0/...` — organizations,
|
||||
projects, issues, events). The design targets **GlitchTip's documented subset**
|
||||
only; Sentry-only endpoints must not be assumed. The implementation should pin
|
||||
against a tested GlitchTip version and treat missing endpoints/fields as
|
||||
degraded-but-safe (omit field, never crash).
|
||||
|
||||
## 4. Minimum read-only tool set
|
||||
|
||||
| Tool | Purpose |
|
||||
|---|---|
|
||||
| `glitchtip_whoami` | Verify authenticated identity + active profile (mirror of `gitea_whoami`; fail-closed identity proof) |
|
||||
| `glitchtip_list_projects` | Projects visible to the token (org-scoped), with pagination bounds |
|
||||
| `glitchtip_list_unresolved` | Unresolved issues for a project, filterable (§6), sorted by last-seen |
|
||||
| `glitchtip_get_issue` | Safe detail of one issue (fields §5) |
|
||||
| `glitchtip_recent_events` | Recent events for an issue (summaries only, §5) |
|
||||
| `glitchtip_search` | Issue search within a project (query + filters §6) |
|
||||
|
||||
All tools are `GET`-only. No tool issues PUT/POST/DELETE.
|
||||
|
||||
## 5. Privacy: field-level allowlist (the core rule)
|
||||
|
||||
Error events routinely contain PII and secrets (request bodies, cookies,
|
||||
headers, tokens, user emails/IPs, local variables). Therefore: **allowlist
|
||||
projection only — raw event/issue payloads are never passed through.**
|
||||
|
||||
### Issue-level safe fields (`glitchtip_list_unresolved`, `glitchtip_get_issue`, `glitchtip_search`)
|
||||
|
||||
| Field | Notes |
|
||||
|---|---|
|
||||
| `issue_id` | GlitchTip issue ID (dedup key for #78) |
|
||||
| `fingerprint` | When available (dedup key for #78) |
|
||||
| `title` / `culprit` | Error type + short message/transaction — redactor-passed |
|
||||
| `project` | Slug |
|
||||
| `level` | error/warning/… |
|
||||
| `status` | unresolved/… |
|
||||
| `environment` | When filtered/available |
|
||||
| `release` | Version string |
|
||||
| `first_seen` / `last_seen` | ISO-8601 UTC |
|
||||
| `event_count` / `user_count` | Numbers only — never user identities |
|
||||
| `permalink` | GlitchTip web URL (the "link, not dump" principle) |
|
||||
|
||||
### Event-level safe fields (`glitchtip_recent_events`)
|
||||
|
||||
`event_id`, `timestamp`, `level`, `environment`, `release`, redactor-passed
|
||||
`message`, and a **stack summary** only: top N (default 5) frames as
|
||||
`module/filename:function:line` — in-app frames preferred.
|
||||
|
||||
### Redact / omit — never returned
|
||||
|
||||
Request headers; cookies; auth/session fields; user emails, usernames, IPs;
|
||||
request/form bodies; query strings; local variables; full raw stack frames
|
||||
(source context lines); SDK/device metadata beyond platform name; breadcrumbs;
|
||||
any `extra`/`context` blobs.
|
||||
|
||||
Full raw frames or request context require a **separate, explicitly approved**
|
||||
operation (`glitchtip.event.read_raw`) that is absent from default profiles —
|
||||
same pattern as `jenkins.console.read` in the #72 design. Even then, output
|
||||
passes the shared secret redactor; redaction failure ⇒ error, never raw text.
|
||||
|
||||
**Default output = fingerprint / release / summary + permalink.** The
|
||||
permalink carries the human to the full data in GlitchTip's own UI, where its
|
||||
access control applies — the MCP layer does not re-serve raw payloads.
|
||||
|
||||
## 6. Filtering and pagination
|
||||
|
||||
Filters (all optional, combinable): `project` (required for issue/event
|
||||
queries), `environment`, `release`, `fingerprint`, free-text `query`
|
||||
(GlitchTip search syntax, e.g. `is:unresolved`).
|
||||
|
||||
Pagination: cursor-based per the API. Bounds: per-page cap 50; default overall
|
||||
cap 100 items; hard cap `max_pages` (default 10) against runaway loops —
|
||||
mirroring `gitea_auth.api_get_all`. Truncation is **explicit** in the return
|
||||
(`"truncated": true`) — never silent.
|
||||
|
||||
## 7. Credentials and profile requirements
|
||||
|
||||
Per-service profile model (`gitea-execution-profiles.md`, extended by #76):
|
||||
|
||||
- Env/config: `GLITCHTIP_URL`, `GLITCHTIP_ORG`, `GLITCHTIP_TOKEN_SOURCE_NAME`
|
||||
(secret **name** only; value resolved at runtime, never logged/committed).
|
||||
- Profile: e.g. `glitchtip-readonly` with namespaced
|
||||
`allowed_operations: ["glitchtip.read", "glitchtip.event.read"]`
|
||||
(+ `glitchtip.event.read_raw` only with explicit approval);
|
||||
`forbidden_operations: ["glitchtip.issue.mutate", "glitchtip.admin"]`
|
||||
belt-and-braces though no mutating tool exists.
|
||||
- Missing URL/org/token/profile ⇒ **fail closed** before any network call.
|
||||
- Read-only ⇒ no confirmation gates; identity (`glitchtip_whoami`) must work so
|
||||
workflows can prove which account they read as.
|
||||
|
||||
## 8. Failure behavior (fail closed, clear, safe)
|
||||
|
||||
| Condition | Behavior |
|
||||
|---|---|
|
||||
| Unknown project/issue | Explicit `{"found": false, ...}` — no fuzzy matching |
|
||||
| GlitchTip unreachable (DNS/timeout) | `"network error contacting GlitchTip: <redacted reason>"` — mirror `gitea_auth.api_request` conversion |
|
||||
| 502/503/504 | "GlitchTip upstream unavailable" |
|
||||
| 401/403 | "GlitchTip auth failed / insufficient permissions" — no credential echo |
|
||||
| 429 | Honor Retry-After with capped jittered backoff (as `gitea_auth`) |
|
||||
| Malformed JSON | "malformed JSON response from GlitchTip" — no raw-body dump |
|
||||
| Missing profile/creds | Fail closed before any network call (§7) |
|
||||
|
||||
All error text passes the shared secret redactor.
|
||||
|
||||
## 9. Testing strategy (mocked; for the implementing package)
|
||||
|
||||
Mocked-GlitchTip unit tests only, per `docs/developer-testing-guidelines.md`:
|
||||
|
||||
- Assert method is always `GET`; URL/filter/cursor shape correct.
|
||||
- **Projection tests:** response fixtures containing emails, IPs, cookies,
|
||||
headers, request bodies, locals, full frames ⇒ none appear in output
|
||||
(explicit negative assertions per §5's redact list).
|
||||
- Stack summary: top-N frame cap enforced; source-context lines absent.
|
||||
- Pagination: per-page/overall/max-pages caps; explicit `truncated` flag.
|
||||
- Filters: environment/release/fingerprint/query passed through correctly.
|
||||
- Failure matrix of §8 incl. no-token-in-error assertions.
|
||||
- Profile gate: missing/insufficient profile ⇒ no network call
|
||||
(`mock_api.assert_not_called()` pattern).
|
||||
- `read_raw` op absent ⇒ raw-frame request refused without an API call.
|
||||
|
||||
## 10. Implementation-readiness checklist
|
||||
|
||||
Ready to implement once:
|
||||
|
||||
1. ADR-0001 owner decision #2 (namespace/placement) is made — mechanical
|
||||
rename of the `glitchtip_` prefix if needed.
|
||||
2. ADR-0001 owner decision #1 (repo home) is made.
|
||||
3. #76 profile schema exists (or a minimal `glitchtip-readonly` profile is
|
||||
hand-rolled to the same rules).
|
||||
4. A pinned GlitchTip version is chosen for API-subset testing (§3).
|
||||
|
||||
Explicitly **not** unlocked by this document: any GlitchTip mutation, any
|
||||
automatic Gitea filing (#74 designs that as a gated, explicitly-invoked
|
||||
orchestrated workflow), any Gitea credentials in this boundary.
|
||||
@@ -1,165 +0,0 @@
|
||||
# Jenkins Repo/Branch/PR → Job Mapping — Design Notes
|
||||
|
||||
- **Status:** Design (implementation-ready notes; **no implementation in this repo**)
|
||||
- **Issue:** #77 (parent: #72 read-only tools design; umbrella: #75; boundary: ADR-0001, #71)
|
||||
- **Related docs:** [`jenkins-readonly-build-status-design.md`](jenkins-readonly-build-status-design.md)
|
||||
- **Date:** 2026-07-02
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
The #72 tool set addresses Jenkins jobs by **explicit fully-qualified job
|
||||
path**. This document designs the layer above it: how a *(repository, branch,
|
||||
PR)* tuple — the vocabulary of Gitea workflows — resolves deterministically to
|
||||
a Jenkins job path, so an LLM can ask "did the build for `Gitea-Tools`
|
||||
`master` pass?" without knowing Jenkins internals.
|
||||
|
||||
Hard constraints inherited from #72 / ADR-0001:
|
||||
|
||||
- **No silent guessing of job names.** Unmapped input returns an explicit
|
||||
"no mapping" result — never a fuzzy match, never a constructed-and-probed
|
||||
name.
|
||||
- **Read-only.** Mapping introduces no Jenkins write actions.
|
||||
- Lives in the **`jenkins-mcp`** boundary; no Gitea credentials involved.
|
||||
|
||||
## 2. Mapping format
|
||||
|
||||
Declarative, versioned config (TOML or JSON — match whatever config format
|
||||
`jenkins-mcp` adopts; illustrated here as TOML):
|
||||
|
||||
```toml
|
||||
version = 1
|
||||
|
||||
[[mapping]]
|
||||
# Source side (what the caller supplies)
|
||||
repo = "Scaled-Tech-Consulting/Gitea-Tools" # org/repo, exact
|
||||
# Target side (where it lives in Jenkins)
|
||||
job = "scaled-tech/gitea-tools" # foldered job path
|
||||
type = "multibranch" # "multibranch" | "single" | "parameterized-view"
|
||||
|
||||
[[mapping]]
|
||||
repo = "Scaled-Tech-Consulting/Timesheet"
|
||||
branch = "master" # optional: branch-specific override
|
||||
job = "scaled-tech/timesheet-master"
|
||||
type = "single"
|
||||
```
|
||||
|
||||
Field semantics:
|
||||
|
||||
| Field | Required | Meaning |
|
||||
|---|---|---|
|
||||
| `repo` | yes | Exact `org/repo` (case-insensitive compare, stored canonical) |
|
||||
| `branch` | no | Exact branch name this entry pins; absent = all branches |
|
||||
| `job` | yes | Fully-qualified Jenkins job path, folders `/`-joined |
|
||||
| `type` | yes | How branch/PR resolves under the job (§3) |
|
||||
|
||||
Rules:
|
||||
|
||||
- **Exact matching only** on `repo` and `branch`. No globs in v1 (globs invite
|
||||
accidental over-matching; add later behind an explicit `pattern = true` flag
|
||||
if ever needed).
|
||||
- Unknown `type` or malformed entry ⇒ config load fails closed with a clear
|
||||
error naming the entry — a broken mapping file must not half-load.
|
||||
- Duplicate `(repo, branch)` keys ⇒ load error (ambiguity is refused, not
|
||||
resolved).
|
||||
|
||||
## 3. Resolution semantics by job type
|
||||
|
||||
Given caller input `(repo, branch?, pr?)`:
|
||||
|
||||
- **`multibranch`** — branch job addressed as `<job>/<url-encoded-branch>`
|
||||
(e.g. `feature/x` → `feature%2Fx`). PRs addressed as `<job>/PR-<number>`
|
||||
(Jenkins multibranch PR-discovery naming). Both per #72 §8.
|
||||
- **`single`** — the job path is used as-is; `branch`/`pr` input beyond the
|
||||
entry's pinned branch is a **no-mapping** result (a single job cannot answer
|
||||
for arbitrary branches).
|
||||
- **`parameterized-view`** — read-only variant for jobs that encode branch as
|
||||
a build parameter: resolution returns the base job path plus a
|
||||
`branch_param` filter hint the status tools may apply client-side when
|
||||
scanning recent builds. It never triggers anything (read-only rule).
|
||||
|
||||
## 4. Precedence
|
||||
|
||||
Most-specific entry wins, evaluated in this order:
|
||||
|
||||
1. `(repo, branch)` exact entry — branch-pinned override.
|
||||
2. `(repo)` entry — repo-wide (multibranch typical).
|
||||
3. Nothing → **no mapping** (§5).
|
||||
|
||||
PR input resolves through the same chain: a PR belongs to its **base repo**'s
|
||||
mapping; forks never introduce their own mapping (a fork's head repo is not
|
||||
consulted — CI runs live under the base repo's job). If the base repo is
|
||||
unmapped, the PR is unmapped.
|
||||
|
||||
Ties are impossible by construction (duplicate keys refused at load).
|
||||
|
||||
## 5. No-match behavior
|
||||
|
||||
```json
|
||||
{
|
||||
"mapped": false,
|
||||
"repo": "org/unknown-repo",
|
||||
"branch": "master",
|
||||
"error": "no Jenkins job mapping for this repo/branch",
|
||||
"hint": "add an entry to the jenkins-mcp mapping config"
|
||||
}
|
||||
```
|
||||
|
||||
- Deterministic, explicit, machine-checkable (`mapped: false`).
|
||||
- **Never** falls back to name construction ("repo name probably equals job
|
||||
name"), never probes Jenkins for candidates, never string-similarity ranks.
|
||||
- The hint names the config, not a guessed job.
|
||||
|
||||
## 6. Where the mapping config lives
|
||||
|
||||
- **In the `jenkins-mcp` package/deployment** (e.g. `jenkins-mcp/mapping.toml`),
|
||||
version-controlled next to the server that consumes it — *not* in Gitea-Tools
|
||||
and *not* in per-user env vars (mappings are shared team facts, not
|
||||
credentials).
|
||||
- Path overridable via env (`JENKINS_MCP_MAPPING_FILE`) for tests/containers.
|
||||
- Contains **no secrets** — job paths and repo names only — so it is safe to
|
||||
commit and review like any other config.
|
||||
- Reloaded at server start; a hot-reload tool is out of scope (restart is the
|
||||
documented path).
|
||||
|
||||
## 7. Exposed tool surface (read-only)
|
||||
|
||||
One addition to the #72 tool set:
|
||||
|
||||
| Tool | Purpose |
|
||||
|---|---|
|
||||
| `jenkins_resolve_job` | `(repo, branch?, pr?)` → `{mapped, job, addressed_path, type}` or the §5 no-match result. Pure config lookup — **no Jenkins API call at all.** |
|
||||
|
||||
Status tools (`jenkins_latest_build` etc.) accept either an explicit job path
|
||||
(as designed in #72) **or** `(repo, branch)` which they resolve via the same
|
||||
mapping layer first. Resolution failure surfaces the §5 payload rather than
|
||||
querying Jenkins.
|
||||
|
||||
## 8. Testing strategy (mocked; for the implementing package)
|
||||
|
||||
Config-layer tests (no network at all):
|
||||
|
||||
- Exact-match hit: repo-wide and branch-pinned entries.
|
||||
- Precedence: branch-pinned beats repo-wide.
|
||||
- Multibranch encoding: `feature/x` → `<job>/feature%2Fx`; PR → `<job>/PR-7`.
|
||||
- `single` type with non-pinned branch ⇒ no-mapping.
|
||||
- Fork PR resolves through base repo; unmapped base ⇒ no-mapping.
|
||||
- Unknown repo/branch ⇒ §5 payload, and **no Jenkins client call**
|
||||
(`mock_api.assert_not_called()`).
|
||||
- Malformed config / duplicate keys / unknown type ⇒ load fails closed with
|
||||
entry-naming error.
|
||||
- No-secret check: mapping load/error paths never touch or print credentials.
|
||||
|
||||
Integration with mocked Jenkins API (per #72 §9): resolved path is used
|
||||
verbatim in the GET URL; no write verbs anywhere.
|
||||
|
||||
## 9. Standalone-worthiness and readiness
|
||||
|
||||
#77 was split from #72 on the condition it stays "standalone only if mapping
|
||||
is nontrivial." The precedence rules, fork/PR semantics, three job types, and
|
||||
fail-closed config loading above are the nontrivial part; this document is the
|
||||
justification.
|
||||
|
||||
Ready to implement in `jenkins-mcp` when #72's readiness checklist clears
|
||||
(ADR-0001 owner decision #1; profile schema per #76 or hand-rolled
|
||||
`jenkins-readonly`). Nothing here unlocks build triggers, deploys, or
|
||||
parameterized launches.
|
||||
@@ -1,68 +0,0 @@
|
||||
# Multi-Service MCP Profile and Configuration Model
|
||||
|
||||
- **Status:** Design (no implementation in this repo yet)
|
||||
- **Issue:** #76 (parent umbrella: #75; boundary decision: ADR-0001, #71)
|
||||
- **Date:** 2026-07-02
|
||||
|
||||
## 1. Purpose and Scope
|
||||
|
||||
Extend the existing Gitea execution-profile model (`docs/gitea-execution-profiles.md`) into a generic **per-service** MCP profile/config model. This supports integrating Jenkins and GlitchTip into the MCP Control Plane while strictly preserving isolation and fail-closed safety.
|
||||
|
||||
**Crucial Constraints:**
|
||||
* The shared profile/config model is a **schema / library**, **not a shared credential pool**.
|
||||
* Tokens remain **service-local**; profiles are **per service**.
|
||||
* Orchestrators **must not** directly hold every service credential.
|
||||
|
||||
## 2. Profile Schema (Per Service)
|
||||
|
||||
The schema reuses the proven Gitea field model, adapted per service.
|
||||
|
||||
```json
|
||||
{
|
||||
"profile_name": "readonly-metrics",
|
||||
"service": "glitchtip",
|
||||
"token_source_name": "GLITCHTIP_API_TOKEN_READONLY",
|
||||
"allowed_operations": [
|
||||
"glitchtip.event.read",
|
||||
"glitchtip.issue.read"
|
||||
],
|
||||
"forbidden_operations": [
|
||||
"glitchtip.issue.resolve",
|
||||
"glitchtip.issue.delete"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Schema Rules
|
||||
|
||||
* `allowed_operations` are **namespaced** (e.g., `gitea.issue.create`, `jenkins.build.read`, `glitchtip.event.read`).
|
||||
* `forbidden_operations`, if present, **always override** `allowed_operations`.
|
||||
* `token_source_name` records the source **name only, never the value**. Tokens must never be printed, logged, or included in telemetry.
|
||||
|
||||
## 3. Fail-Closed Behavior
|
||||
|
||||
The model enforces strict fail-closed constraints before any network call occurs:
|
||||
* **Missing Profile:** If a requested profile is undefined for the target service, the operation fails immediately.
|
||||
* **Missing Credentials:** If the `token_source_name` cannot be resolved to a valid token at runtime, the operation fails immediately without retrying or prompting.
|
||||
|
||||
## 4. Environment Overrides
|
||||
|
||||
Profiles can be dynamically overridden or injected via environment variables, following the established hierarchy:
|
||||
|
||||
1. **Explicit Environment Variable:** (Highest precedence) e.g., `MCP_GLITCHTIP_TOKEN` overrides any JSON profile.
|
||||
2. **Profile Mapping in JSON:** Resolved via `token_source_name` (e.g., `GLITCHTIP_API_TOKEN_READONLY`) mapping to an environment variable or secret store.
|
||||
3. **No Auth:** Fails closed.
|
||||
|
||||
## 5. Audit Logging
|
||||
|
||||
To maintain accountability across multi-service workflows, all mutating actions must include the audit identity and source:
|
||||
* The audit log must record the `profile_name`, the orchestrator source (e.g., `sysadmin`, `jenkins-mcp`), and the action taken.
|
||||
* The audit system must sanitize all output to ensure tokens are stripped (see `safety-model.md`).
|
||||
|
||||
## 6. Backward Compatibility
|
||||
|
||||
The existing Gitea profile behavior (`gitea_whoami`, etc.) remains strictly backward compatible. The generic profile library will parse existing Gitea profile objects without requiring them to migrate their schemas, defaulting the `service` attribute to `gitea`.
|
||||
|
||||
## 7. Implementation Boundary
|
||||
|
||||
Per the namespace decisions in #71 and #75, this generic model belongs in the `common` package or library. It will be imported by `gitea-mcp` (this repo), `jenkins-mcp`, and `glitchtip-mcp` without forcing a monolithic architecture.
|
||||
@@ -5,5 +5,5 @@ This document describes how credentials and sensitive environment variables are
|
||||
## Separate Credentials
|
||||
Even though multiple MCP servers share the same monorepo, they **must** have separate credentials and runtimes.
|
||||
|
||||
- **No Shared Environments**: Each MCP server (`gitea-mcp`, `jenkins-mcp`, `glitchtip-mcp`, `ops-mcp`, etc.) must be instantiated as an independent service with its own dedicated `.env` configuration file.
|
||||
- **No Shared Environments**: Each MCP server (`gitea-mcp`, `jenkins-mcp`, `ops-mcp`, etc.) must be instantiated as an independent service with its own dedicated `.env` configuration file.
|
||||
- **Strict Isolation**: A server will only have access to the credentials required for its specific trust boundary. For instance, `gitea-mcp` has no access to Jenkins or Ops authentication tokens.
|
||||
|
||||
@@ -13,11 +13,3 @@ To maintain a secure environment, all secrets, tokens, passwords, and sensitive
|
||||
- System and application logs
|
||||
- Tool return values/outputs
|
||||
- Any form of persistent storage or console output
|
||||
|
||||
## 4. Read-Only First Policy
|
||||
By default, MCP servers (such as `jenkins-mcp` and `ops-mcp`) operate in a **read-only** mode. Mutation capabilities are deny-by-default and fail-closed.
|
||||
|
||||
## 5. Mutation Gating
|
||||
Any mutating action (e.g., Gitea issue creation from GlitchTip, or Jenkins builds) must be explicitly allowed by the execution profile.
|
||||
- **Jenkins build triggers** are explicitly deferred for phase 1.
|
||||
- **GlitchTip to Gitea issue filing** is documented as a gated, orchestrated workflow, not a direct unprompted automatic action.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
This document defines the strict boundaries between the different MCP server packages within the monorepo.
|
||||
|
||||
The project is named **MCP Control Plane** and lives in the `mcp-control-plane` repository. It groups the following packages: `common`, `gitea-mcp`, `jenkins-mcp`, `glitchtip-mcp`, `ops-mcp`, and `release-mcp`.
|
||||
The project is named **MCP Control Plane** and lives in the `mcp-control-plane` repository. It groups the following packages: `common`, `gitea-mcp`, `jenkins-mcp`, `ops-mcp`, and `release-mcp`.
|
||||
|
||||
## 1. Architectural Philosophy
|
||||
- **One MCP Server per Trust Boundary**: While the packages share a monorepo, their runtime services must remain entirely separate. There is no single "everything" server.
|
||||
@@ -10,5 +10,4 @@ The project is named **MCP Control Plane** and lives in the `mcp-control-plane`
|
||||
## 2. Package-Specific Boundaries
|
||||
- **gitea-mcp**: Restricted to source-control and work-item capabilities (issues, PRs, comments). This package **must not** have Jenkins or Ops credentials, nor can it execute deploy operations.
|
||||
- **jenkins-mcp**: Focused on CI/CD capabilities. This package **must not** have Ops credentials unless explicitly configured for a specific, isolated pipeline later.
|
||||
- **glitchtip-mcp**: Dedicated to observability and error reporting. This package **must not** have Gitea write credentials or Jenkins deploy capabilities.
|
||||
- **ops-mcp**: Dedicated to live environment and host checks. In its initial state, this package starts as strictly read-only (e.g., health checks, status checks, log reading).
|
||||
|
||||
Reference in New Issue
Block a user