Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
e26bd2b
feat: include additional namespaces in Zenodo CSV export
bencap Feb 6, 2026
5701190
feat: add boolean `include_superseding` to `transform_score_set_list_…
bencap Feb 16, 2026
d55790c
feat: implement user-controllable ordering for collection datasets
bencap Feb 16, 2026
cd4bfc5
chore: remove deprecated pkg_resources and replace w stdlib. Bump pan…
bencap Feb 13, 2026
31d4e46
fix: use na_rep instead of string 'None' for missing score and count …
bencap Feb 17, 2026
118e7c1
chore: remove deprecated pkg_resources and replace w stdlib. Bump pan…
bencap Feb 13, 2026
721ffea
chore: add ExCALIBR calibration loading script and remove deprecated …
bencap Feb 18, 2026
689841e
feat: remove variants from calibration responses, add dedicated varia…
bencap Feb 19, 2026
2e46417
chore: remove deprecated pkg_resources and replace w stdlib. Bump pan…
bencap Feb 13, 2026
ecfe8ad
chore: Replace generic Copilot instruction boilerplate with MaveDB-sp…
bencap Feb 20, 2026
3f42725
feat: remove variants from calibration responses, add dedicated varia…
bencap Feb 19, 2026
f8b1faa
fix: simplify permission check logic gates in collections.py
bencap Feb 23, 2026
5efa5fa
refactor: add ADD_CALIBRATION permission action for score sets
bencap Feb 23, 2026
be6582a
feat: enhance performance by adding eager loading for functional clas…
bencap Feb 23, 2026
00a2bc7
fix: don't hide published score sets from search when superseded by u…
bencap Feb 24, 2026
a96cab7
feat: allow independent users to create score calibrations on publish…
bencap Feb 23, 2026
3ff28aa
refactor: rename classification sources to evidence in score calibrat…
bencap Feb 24, 2026
a247f27
Merge pull request #661 from VariantEffect/bugfix/bencap/636/na-rep-n…
bencap Feb 24, 2026
c21428a
fix: rename parameter `include_superseding` to `include_superseded` f…
bencap Feb 24, 2026
3905f15
Merge pull request #660 from VariantEffect/feature/bencap/612/sortabl…
bencap Feb 25, 2026
17c65e5
Merge pull request #662 from VariantEffect/chore/bencap/excalibr-cali…
bencap Feb 25, 2026
3a13731
Merge pull request #665 from VariantEffect/chore/bencap/agent-md-impr…
bencap Feb 25, 2026
0af96a9
Merge branch 'release-2026.1.1' into feature/bencap/539/broaden-calib…
bencap Feb 25, 2026
79d4fda
Merge branch 'release-2026.1.1' into bugfix/bencap/656/search-not-ret…
bencap Feb 25, 2026
94556d7
docs: add section on maintaining living documentation for code changes
bencap Feb 25, 2026
ee36ec6
Merge pull request #667 from VariantEffect/bugfix/bencap/656/search-n…
bencap Feb 26, 2026
f866325
Return default alphafold version when parsing or request for XML fails
davereinhart Feb 27, 2026
87a790e
Remove unused import
davereinhart Feb 27, 2026
de9d276
Merge pull request #670 from VariantEffect/davereinhart/default-alpha…
davereinhart Feb 27, 2026
f28e36a
Merge pull request #654 from VariantEffect/feature/bencap/643/include…
bencap Mar 2, 2026
f98915d
Merge pull request #663 from VariantEffect/feature/bencap/659/calibra…
bencap Mar 2, 2026
9931de8
Merge branch 'release-2026.1.1' into feature/bencap/539/broaden-calib…
bencap Mar 2, 2026
ae28131
Merge pull request #666 from VariantEffect/feature/bencap/539/broaden…
bencap Mar 2, 2026
47e815b
chore: bump dependencies for Dependabot security updates
bencap Mar 2, 2026
50fd667
chore: bump version to 2026.1.1
bencap Mar 2, 2026
48112fb
chore: deterministic ordering of db migrations
bencap Mar 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

140 changes: 140 additions & 0 deletions .github/instructions/api.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
---
description: 'MaveDB API patterns — routers, authentication, authorization, endpoints'
applyTo: 'src/mavedb/routers/**/*.py'
---

# API Patterns for MaveDB

## Router Structure

All routers use:
- `ROUTER_BASE_PREFIX = "/api/v1"` from `src/mavedb/routers/__init__.py`
- `LoggedRoute` as the custom `route_class` for canonical request/response logging
- Kebab-case URL paths: `/score-sets`, `/experiment-sets`

```python
router = APIRouter(
prefix="/api/v1/score-sets",
tags=["score-sets"],
route_class=LoggedRoute,
responses=shared_responses,
)
```

## Authentication

Three tiers of auth dependency injection:

| Dependency | Returns | Use When |
|-----------|---------|----------|
| `get_current_user` | `Optional[UserData]` | Public endpoints that behave differently for authenticated users |
| `require_current_user` | `UserData` | Endpoints requiring login |
| `require_current_user_with_email` | `UserData` | Endpoints requiring verified email (write operations) |

Auth supports two mechanisms:
- **ORCID JWT tokens** — primary auth for web users
- **API keys** — for programmatic access

```python
@router.get("/{urn}")
def get_score_set(
urn: str,
db: Session = Depends(get_db),
user: Optional[UserData] = Depends(get_current_user),
):
...
```

## Authorization

Permission checks use the `assert_permission()` helper with an `Action` enum:

```python
from mavedb.lib.authorization import assert_permission, Action

assert_permission(user, item, Action.READ) # View
assert_permission(user, item, Action.UPDATE) # Modify
assert_permission(user, item, Action.DELETE) # Delete
assert_permission(user, item, Action.ADD_ROLE) # Manage contributors
```

Key authorization behaviors:
- **Private resources return 404** (not 403) to prevent information leakage about existence
- Permission logic dispatches by resource type (ExperimentSet, Experiment, ScoreSet, etc.)
- Admins bypass most permission checks

## Endpoint Patterns

### Standard CRUD
```python
@router.get("/", response_model=list[ScoreSetShortModel])
def list_score_sets(db: Session = Depends(get_db)): ...

@router.get("/{urn}", response_model=ScoreSetFullModel)
def get_score_set(urn: str, db: Session = Depends(get_db)): ...

@router.post("/", response_model=ScoreSetSavedModel, status_code=201)
def create_score_set(body: ScoreSetCreateModel, db: Session = Depends(get_db)): ...

@router.put("/{urn}", response_model=ScoreSetSavedModel)
def update_score_set(urn: str, body: ScoreSetUpdateModel, db: Session = Depends(get_db)): ...

@router.delete("/{urn}", status_code=204)
def delete_score_set(urn: str, db: Session = Depends(get_db)): ...
```

### Background Job Enqueueing
For operations that trigger async processing:
```python
@router.post("/{urn}:publish")
async def publish_score_set(
urn: str,
db: Session = Depends(get_db),
user: UserData = Depends(require_current_user_with_email),
worker: ArqRedis = Depends(get_worker),
):
# ... validation and DB updates ...
await worker.enqueue_job(
"create_variants_for_score_set",
score_set.id,
correlation_id,
)
```

### Error Responses
Shared error response definitions are used across routers:
```python
responses=shared_responses # Defines 4xx/5xx response schemas
```

## Worker Integration

### Job Pipeline
Many operations chain through multiple worker jobs:
1. `create_variants_for_score_set` — Parse uploaded CSV, create variant records
2. `map_variants_for_score_set` — Map variants via DCD Mapping / VRS
3. `submit_score_set_mappings_to_*` — Submit to ClinGen services

### Job Patterns
```python
async def create_variants_for_score_set(ctx: dict, score_set_id: int, correlation_id: str):
logging_context = setup_job_state(ctx, correlation_id)
db = ctx["db"]

try:
# ... processing ...
pass
except Exception as e:
send_slack_error(e, logging_context)
raise
```

### Backoff and Retry
Use `enqueue_job_with_backoff()` for jobs that may need retries (e.g., external service calls).

## Correlation IDs
Every request gets a correlation ID via starlette-context middleware. Pass it to worker jobs for end-to-end request tracing:
```python
from mavedb.lib.logging.context import save_to_logging_context
correlation_id = save_to_logging_context({"score_set_urn": urn})
```
Loading