Canonical Reference: See
/AGENTS.mdfor the unified Dev Health platform agent briefing.Deep Dives: See
/docs/agent-instructions/connectors/atlassian-graphql.mdfor detailed AGG client documentation.
This repository implements a production-grade Atlassian GraphQL Gateway (AGG) client and analytics pipeline (Python + Go) used to collect Jira (and related Atlassian product) data and compute developer health metrics.
This file defines non-negotiable rules, architecture boundaries, and operating principles for any human or AI agent modifying this repository.
If you violate these rules, your changes are incorrect even if the code “works”.
-
Schema-driven, not guess-driven
- Atlassian GraphQL schemas evolve.
- API models MUST be generated from live schema introspection, not handwritten guesses.
- Canonical analytics models MUST be stable and owned by this repo.
-
Separation of concerns is mandatory
- API models ≠ analytics models.
- Transport ≠ business logic.
- Fetching ≠ mapping ≠ metric computation.
-
Defensive by default
- Expect partial data, missing fields, pagination edge cases, and rate limiting.
- Fail loudly and explicitly when required data is missing.
- Never silently drop errors.
-
Production realism
- Rate limits are real.
- Schemas change.
- Tenants differ.
- Permissions vary.
- Code must degrade gracefully.
Purpose: Represent the Atlassian GraphQL Gateway schema as it exists today.
Characteristics:
- Generated from GraphQL introspection
- Allowed to change frequently
- Mirrors AGG types (connections, edges, nodes, pageInfo)
- NOT used directly for analytics
Locations:
python/atlassian/graph/gen/python/atlassian/rest/gen/go/atlassian/graph/gen/go/atlassian/rest/gen/- Source schema:
graphql/schema.introspection.json
Rules:
- Never hand-edit generated files
- Regeneration must be deterministic
- Missing schema fields MUST cause generator failure
Purpose: Safely execute GraphQL operations against AGG.
Responsibilities:
- Authentication
- Rate limiting
- Retries (429 only)
- Logging
- Strict vs non-strict GraphQL error handling
- Beta headers (
X-ExperimentalApi)
Locations:
python/atlassian/graph/client.pypython/atlassian/rest/client.pygo/atlassian/graph/client.gogo/atlassian/rest/client.go
Hard Rules:
- Retry ONLY on HTTP 429
- Parse
Retry-Afteras a TIMESTAMP - NEVER retry HTTP >= 500
- Do NOT log secrets
- Timeouts are mandatory
Purpose: Define the data model used for developer health metrics.
Characteristics:
- API-agnostic
- Versioned by this repo
- Backward-compatible whenever possible
- Designed for analytics, not transport convenience
Source of Truth:
openapi/jira-developer-health.canonical.openapi.yaml(Jira)openapi/compass-developer-health.canonical.openapi.yaml(Compass)openapi/teams-developer-health.canonical.openapi.yaml(Teams)
Examples:
- JiraUser, JiraProject, JiraIssue, JiraChangelogEvent, JiraWorklog
- CompassComponent, CompassRelationship, CompassScorecardScore
- AtlassianTeam, AtlassianTeamMember
- CanonicalProjectWithOpsgenieTeams
Rules:
- Canonical schemas must NOT leak API-specific shapes (edges, nodes, cursors)
- IDs are strings
- Timestamps are RFC3339
- Optional fields are preferred over brittle requirements
Purpose: Convert API models → canonical analytics models.
Locations:
python/atlassian/graph/mappers/python/atlassian/rest/mappers/go/atlassian/graph/mappers/go/atlassian/rest/mappers/
Rules:
- Required canonical fields MUST be validated
- Missing required data → explicit error
- No implicit defaults for semantic fields
- Positive conditionals preferred
- No business logic here — mapping only
Purpose: Expose Jira data (projects, issues, etc.) as Terraform data sources and resources for lifecycle management (Read, Create, Update, Delete).
Rules:
- REST-only: Uses Jira REST API, not GraphQL.
- Generated models: Uses generated REST models from
atlassian/rest/gen/. - Canonical alignment: Must remain aligned with canonical schemas in
openapi/. - Location:
atlassian/terraform/(Provider:registry.terraform.io/full-chaos/jira)
-
Assume every connection paginates
-
Support:
pageInfo.hasNextPagepageInfo.endCursorif present
-
Nested pagination MUST be handled (e.g. projects → opsgenie teams)
-
Never assume a single page
-
Never hardcode page sizes
-
Atlassian AGG uses cost-based rate limiting
-
Default budget: 10,000 points per minute
-
Enforcement mechanism:
- HTTP 429
Retry-Afterheader contains a timestamp, not seconds
Behavior:
- Retry ONLY on 429
- Compute wait = retry_after_timestamp - now
- Cap wait using MaxWait
- After MaxRetries429 → fail with RateLimitError
- Do NOT retry 4xx (except 429)
- Do NOT retry >= 500
Violating this will get your code reverted.
Supported auth modes:
- OAuth Bearer token (
Authorization: Bearer) - Basic auth (email + API token) for tenant gateway
- Cookie-based auth (explicit, opt-in)
Rules:
- Auth MUST be injectable
- Never hardcode tokens
- Never log auth headers or cookies
- Tests MUST mock auth
-
MUST mock HTTP
-
MUST cover:
- Pagination
- Rate limiting (429)
- Beta headers
- Mapping validation
- Error paths
- MUST be env-gated
- MUST skip cleanly if env vars missing
- MUST NOT attempt to intentionally trigger rate limits
- MUST assert shape, not volume
-
ATLASSIAN_GQL_BASE_URL -
One of:
ATLASSIAN_OAUTH_ACCESS_TOKENATLASSIAN_EMAIL+ATLASSIAN_API_TOKENATLASSIAN_COOKIES_JSON
If you are an AI agent (Codex, Copilot, Claude, etc.):
- NEVER commit directly to main — Always create a feature branch first:
git checkout -b <type>/<descriptive-name> # e.g., fix/rate-limit, feat/compass-sync
- DO NOT invent GraphQL fields
- DO NOT assume schema stability
- DO NOT collapse API models into analytics models
- DO NOT remove rate-limiting safeguards
- DO NOT weaken error handling to “make tests pass”
- DO NOT introduce silent fallbacks
If schema details are unclear:
- Fetch introspection
- Inspect schema
- Generate models
- Map explicitly
Guessing is a failure.
- Not a thin demo client
- Not a static schema wrapper
- Not a Jira-only system
- Not tolerant of silent data corruption
Canonical Reference: See
/AGENTS.mdfor full documentation.
External tracker: Linear project/cycle views.
# bd (local task tracking)
bd create "Task title" --priority P2 --external-ref ENG-123
bd list --status open
bd status <id> in-progress
bd status <id> done
bd dep add <child-id> <parent-id> --type parent-child
bd sync
# Linear issue linkage (team issue key)
# Example: ENG-123- Create bd issue with
--external-ref <TEAM>-NNNto link to Linear - Update bd status during work
- Run
bd syncbeforegit push - Close/update the linked Linear issue when complete
If there is a conflict between:
- Code comments
- README
- AGENTS.md
AGENTS.md wins.
If you are unsure how to proceed:
- Preserve correctness
- Preserve explicitness
- Preserve future schema evolution
That is the bar.
When ending a work session, you MUST complete ALL steps below. Work is NOT complete until git push succeeds.
MANDATORY WORKFLOW:
- File issues for remaining work - Create issues for anything that needs follow-up
- Run quality gates (if code changed) - Tests, linters, builds
- Update issue status - Close finished work, update in-progress items
- PUSH TO REMOTE - This is MANDATORY:
git pull --rebase bd sync git push git status # MUST show "up to date with origin" - Clean up - Clear stashes, prune remote branches
- Verify - All changes committed AND pushed
- Hand off - Provide context for next session
CRITICAL RULES:
- Work is NOT complete until
git pushsucceeds - NEVER stop before pushing - that leaves work stranded locally
- NEVER say "ready to push when you are" - YOU must push
- If push fails, resolve and retry until it succeeds