Skip to content

Commit 99b4f3e

Browse files
authored
chore: align repo hygiene and docs (#2)
1 parent 257a7b2 commit 99b4f3e

File tree

14 files changed

+302
-92
lines changed

14 files changed

+302
-92
lines changed

.github/workflows/ci.yml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: ['*']
6+
pull_request:
7+
branches: [main]
8+
9+
env:
10+
PYTHON_VERSION: '3.11'
11+
12+
jobs:
13+
lint:
14+
name: Code Quality (Ruff)
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- name: Set up Python
20+
uses: actions/setup-python@v5
21+
with:
22+
python-version: ${{ env.PYTHON_VERSION }}
23+
24+
- name: Install Ruff
25+
run: pip install ruff
26+
27+
- name: Run Ruff check
28+
run: ruff check dewey_service tests
29+
30+
- name: Run Ruff format check
31+
run: ruff format --check dewey_service tests
32+
33+
security:
34+
name: Security Scanning (Bandit)
35+
runs-on: ubuntu-latest
36+
steps:
37+
- uses: actions/checkout@v4
38+
39+
- name: Set up Python
40+
uses: actions/setup-python@v5
41+
with:
42+
python-version: ${{ env.PYTHON_VERSION }}
43+
44+
- name: Install Bandit
45+
run: pip install "bandit[toml]"
46+
47+
- name: Run Bandit security scan
48+
run: bandit -c pyproject.toml -r dewey_service
49+
50+
test:
51+
name: Tests and Build
52+
runs-on: ubuntu-latest
53+
needs: [lint, security]
54+
steps:
55+
- uses: actions/checkout@v4
56+
57+
- name: Set up Python
58+
uses: actions/setup-python@v5
59+
with:
60+
python-version: ${{ env.PYTHON_VERSION }}
61+
cache: pip
62+
63+
- name: Install dependencies
64+
run: |
65+
python -m pip install --upgrade pip
66+
pip install -e ".[dev]"
67+
68+
- name: Run tests
69+
run: pytest
70+
71+
- name: Build package
72+
run: python -m build

.pre-commit-config.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
repos:
2+
- repo: https://github.com/astral-sh/ruff-pre-commit
3+
rev: v0.15.1
4+
hooks:
5+
- id: ruff
6+
args: [--fix, --exit-non-zero-on-fix]
7+
- id: ruff-format
8+
9+
- repo: https://github.com/PyCQA/bandit
10+
rev: 1.9.4
11+
hooks:
12+
- id: bandit
13+
args: ["-c", "pyproject.toml"]
14+
additional_dependencies: ["bandit[toml]"]
15+
16+
- repo: https://github.com/pre-commit/pre-commit-hooks
17+
rev: v5.0.0
18+
hooks:
19+
- id: trailing-whitespace
20+
- id: end-of-file-fixer
21+
- id: check-yaml
22+
- id: check-added-large-files
23+
args: ["--maxkb=500"]
24+
- id: check-merge-conflict
25+
- id: detect-private-key

README.md

Lines changed: 62 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,43 @@
11
# Dewey
22

3-
Dewey is the canonical artifact registry and artifact-resolution platform service for LSMC.
3+
Dewey is the canonical artifact registry and artifact-resolution service in this workspace.
44

5-
## Authority Scope
5+
It owns:
66

7-
Dewey is authoritative for:
7+
- artifact identity and metadata
8+
- artifact-set identity and membership
9+
- artifact resolution and storage metadata lookup
10+
- share-reference issuance
11+
- external object links to artifacts and artifact sets
812

9-
- `artifact` identity and metadata
10-
- `artifact_set` identity and membership
11-
- storage metadata and artifact resolution
12-
- `share_reference` issuance
13-
- registration/import of artifacts
14-
- external cross-system artifact links
13+
It does not own:
1514

16-
Dewey does not own Atlas release visibility or attachment policy decisions.
15+
- customer release visibility decisions
16+
- Atlas storage policy authority
17+
- Bloom or Ursa execution state
1718

18-
## Quick Start
19+
## Runtime Shape
1920

20-
```bash
21-
cd /Users/jmajor/projects/lims3/dewey
22-
source dewey_activate
23-
python -m pip install -e .[dev]
24-
dewey db build --target local
25-
dewey server start --port 8913
26-
```
21+
Primary package: `dewey_service`
2722

28-
TapDB local dev uses port `5439` via `config/tapdb-config-dewey.yaml`.
23+
Primary entrypoints:
2924

30-
## Auth
25+
- app factory: `dewey_service.app:create_app`
26+
- CLI command: `dewey`
3127

32-
- API: `Authorization: Bearer <token>` is required for all `/api/*` routes.
33-
- UI: Cognito Hosted UI session auth (`/auth/login` -> `/auth/callback`).
34-
- Mutating API routes require `Idempotency-Key`.
28+
The service exposes both API routes and a small Cognito-backed operator UI.
3529

36-
## Canonical API Routes
30+
## API Surface
31+
32+
Current routes:
3733

38-
- `POST /api/v1/artifacts`
39-
- `POST /api/v1/artifacts/import`
4034
- `GET /api/v1/artifacts`
4135
- `GET /api/v1/artifacts/{artifact_euid}`
42-
- `POST /api/v1/artifact-sets`
36+
- `POST /api/v1/artifacts`
37+
- `POST /api/v1/artifacts/import`
4338
- `GET /api/v1/artifact-sets`
4439
- `GET /api/v1/artifact-sets/{artifact_set_euid}`
40+
- `POST /api/v1/artifact-sets`
4541
- `POST /api/v1/artifact-sets/{artifact_set_euid}/members`
4642
- `DELETE /api/v1/artifact-sets/{artifact_set_euid}/members/{artifact_euid}`
4743
- `POST /api/v1/resolve/artifact`
@@ -51,16 +47,45 @@ TapDB local dev uses port `5439` via `config/tapdb-config-dewey.yaml`.
5147
- `POST /api/v1/external-object-relations`
5248
- `GET /api/v1/{target_type}/{target_euid}/external-object-relations`
5349

54-
## CLI Groups
50+
UI/auth routes:
51+
52+
- `/login`
53+
- `/auth/login`
54+
- `/auth/callback`
55+
- `/ui`
56+
- `POST /logout`
57+
58+
## Auth
59+
60+
- API routes require `Authorization: Bearer <token>`
61+
- mutating API routes require `Idempotency-Key`
62+
- operator UI uses Cognito Hosted UI session auth
63+
64+
## CLI Surface
65+
66+
Primary groups:
67+
68+
- `dewey server`: start the API/UI server
69+
- `dewey db`: build, seed, reset Dewey on top of TapDB
70+
- `dewey tapdb`: pass through TapDB commands in Dewey runtime context
71+
- `dewey cognito`: Cognito/daycog helper commands
72+
- `dewey test`, `dewey quality`, `dewey config`, `dewey env`
73+
74+
## Quick Start
5575

5676
```bash
57-
dewey info
58-
dewey server start --help
59-
dewey db --help
60-
dewey tapdb --help
61-
dewey cognito --help
62-
dewey test --help
63-
dewey quality --help
64-
dewey config --help
65-
dewey env --help
77+
source dewey_activate
78+
pip install -e .[dev]
79+
dewey db build --target local
80+
dewey server start --port 8913 --no-ssl
6681
```
82+
83+
For production-like local HTTPS, place certs at `certs/localhost.pem` and `certs/localhost-key.pem` and omit `--no-ssl`.
84+
85+
## Current Docs
86+
87+
- [Docs index](docs/README.md)
88+
89+
Historical cutover planning lives in `docs/` as background only.
90+
91+
<!-- release-sweep: 2026-03-10 -->

dewey_service/app.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,9 @@ async def logout(request: Request) -> RedirectResponse:
205205
return RedirectResponse(url=logout_url, status_code=status.HTTP_303_SEE_OTHER)
206206

207207
@app.get("/ui", include_in_schema=False)
208-
async def ui_home(request: Request, profile: dict[str, Any] = Depends(require_ui_session)) -> HTMLResponse:
208+
async def ui_home(
209+
request: Request, profile: dict[str, Any] = Depends(require_ui_session)
210+
) -> HTMLResponse:
209211
artifacts = service.list_artifacts(limit=100)
210212
artifact_sets = service.list_artifact_sets(limit=100)
211213
return templates.TemplateResponse(

dewey_service/cli.py

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from __future__ import annotations
44

55
import os
6+
import shutil
67
import subprocess
78
import sys
89
from pathlib import Path
@@ -65,7 +66,7 @@ def info() -> None:
6566

6667
@server_app.command("start")
6768
def server_start(
68-
host: str = typer.Option("0.0.0.0", "--host", help="Host to bind"),
69+
host: str = typer.Option("127.0.0.1", "--host", help="Host to bind"),
6970
port: int = typer.Option(8913, "--port", "-p", help="Port to bind"),
7071
reload: bool = typer.Option(False, "--reload/--no-reload", help="Enable autoreload"),
7172
ssl: bool = typer.Option(True, "--ssl/--no-ssl", help="Serve over HTTPS"),
@@ -96,7 +97,9 @@ def db_build(
9697
cluster: str = typer.Option("", "--cluster", help="Aurora cluster ID for aurora target"),
9798
profile: str = typer.Option(DEFAULT_AWS_PROFILE, "--profile", help="AWS profile"),
9899
region: str = typer.Option(DEFAULT_AWS_REGION, "--region", help="AWS region"),
99-
namespace: str = typer.Option(DEFAULT_TAPDB_DATABASE_NAME, "--namespace", help="TapDB namespace"),
100+
namespace: str = typer.Option(
101+
DEFAULT_TAPDB_DATABASE_NAME, "--namespace", help="TapDB namespace"
102+
),
100103
) -> None:
101104
"""Bootstrap TapDB runtime and apply Dewey overlay."""
102105
ensure_tapdb_version()
@@ -115,7 +118,15 @@ def db_build(
115118
if not cluster.strip():
116119
raise TapDBRuntimeError("--cluster is required for aurora target")
117120
result = run_tapdb_cli(
118-
["bootstrap", "aurora", "--cluster", cluster.strip(), "--region", region, "--no-gui"],
121+
[
122+
"bootstrap",
123+
"aurora",
124+
"--cluster",
125+
cluster.strip(),
126+
"--region",
127+
region,
128+
"--no-gui",
129+
],
119130
target=target,
120131
client_id=DEFAULT_TAPDB_CLIENT_ID,
121132
profile=profile,
@@ -135,7 +146,9 @@ def db_build(
135146
console.print(f"[green]DATABASE_URL[/green] resolved: [dim]{db_url}[/dim]")
136147

137148
# Overlay step: bootstrap Dewey templates through app service.
138-
subprocess.run([sys.executable, "-m", "dewey_service.db_seed"], cwd=PROJECT_ROOT, check=True)
149+
subprocess.run(
150+
[sys.executable, "-m", "dewey_service.db_seed"], cwd=PROJECT_ROOT, check=True
151+
)
139152
console.print("[green]Dewey TapDB overlay complete[/green]")
140153
except (TapDBRuntimeError, subprocess.CalledProcessError) as exc:
141154
console.print(f"[red]DB build failed:[/red] {exc}")
@@ -146,7 +159,9 @@ def db_build(
146159
def db_seed() -> None:
147160
"""Apply Dewey TapDB template overlay only."""
148161
try:
149-
subprocess.run([sys.executable, "-m", "dewey_service.db_seed"], cwd=PROJECT_ROOT, check=True)
162+
subprocess.run(
163+
[sys.executable, "-m", "dewey_service.db_seed"], cwd=PROJECT_ROOT, check=True
164+
)
150165
except subprocess.CalledProcessError as exc:
151166
raise typer.Exit(exc.returncode) from exc
152167

@@ -157,7 +172,9 @@ def db_reset(
157172
target: str = typer.Option("local", "--target", help="TapDB target: local|aurora"),
158173
profile: str = typer.Option(DEFAULT_AWS_PROFILE, "--profile", help="AWS profile"),
159174
region: str = typer.Option(DEFAULT_AWS_REGION, "--region", help="AWS region"),
160-
namespace: str = typer.Option(DEFAULT_TAPDB_DATABASE_NAME, "--namespace", help="TapDB namespace"),
175+
namespace: str = typer.Option(
176+
DEFAULT_TAPDB_DATABASE_NAME, "--namespace", help="TapDB namespace"
177+
),
161178
) -> None:
162179
"""Delete and rebuild TapDB target then apply Dewey overlay."""
163180
if not force and not typer.confirm("This will delete the current TapDB DB target. Continue?"):
@@ -188,7 +205,9 @@ def tapdb_run(
188205
target: str = typer.Option("local", "--target", help="TapDB target: local|aurora"),
189206
profile: str = typer.Option(DEFAULT_AWS_PROFILE, "--profile", help="AWS profile"),
190207
region: str = typer.Option(DEFAULT_AWS_REGION, "--region", help="AWS region"),
191-
namespace: str = typer.Option(DEFAULT_TAPDB_DATABASE_NAME, "--namespace", help="TapDB namespace"),
208+
namespace: str = typer.Option(
209+
DEFAULT_TAPDB_DATABASE_NAME, "--namespace", help="TapDB namespace"
210+
),
192211
) -> None:
193212
"""Run raw tapdb CLI arguments through Dewey runtime context."""
194213
if not ctx.args:
@@ -218,9 +237,13 @@ def tapdb_run(
218237
@cognito_app.command("status")
219238
def cognito_status() -> None:
220239
"""Show daycog status for Dewey runtime."""
240+
daycog_path = shutil.which("daycog")
241+
if not daycog_path:
242+
console.print("[red]daycog not found in PATH[/red]")
243+
raise typer.Exit(1)
221244
try:
222245
proc = subprocess.run(
223-
["daycog", "status"],
246+
[daycog_path, "status"],
224247
capture_output=True,
225248
text=True,
226249
check=False,
@@ -242,7 +265,7 @@ def test_run(
242265
pytest_args: list[str] = typer.Argument(
243266
None,
244267
help="Optional pytest arguments, e.g. tests/test_app_boot.py -q",
245-
)
268+
),
246269
) -> None:
247270
"""Run Dewey tests."""
248271
args = list(pytest_args or ["-q"])
@@ -257,12 +280,16 @@ def test_run(
257280
@quality_app.command("lint")
258281
def quality_lint() -> None:
259282
"""Run Ruff lint checks."""
260-
proc = subprocess.run([sys.executable, "-m", "ruff", "check", "."], cwd=PROJECT_ROOT, check=False)
283+
proc = subprocess.run(
284+
[sys.executable, "-m", "ruff", "check", "."], cwd=PROJECT_ROOT, check=False
285+
)
261286
raise typer.Exit(proc.returncode)
262287

263288

264289
@quality_app.command("format")
265-
def quality_format(check: bool = typer.Option(True, "--check/--fix", help="Check or apply formatting")) -> None:
290+
def quality_format(
291+
check: bool = typer.Option(True, "--check/--fix", help="Check or apply formatting"),
292+
) -> None:
266293
"""Run Ruff formatter."""
267294
cmd = [sys.executable, "-m", "ruff", "format", "."]
268295
if check:
@@ -274,7 +301,9 @@ def quality_format(check: bool = typer.Option(True, "--check/--fix", help="Check
274301
@quality_app.command("check")
275302
def quality_check() -> None:
276303
"""Run lint then tests."""
277-
lint = subprocess.run([sys.executable, "-m", "ruff", "check", "."], cwd=PROJECT_ROOT, check=False)
304+
lint = subprocess.run(
305+
[sys.executable, "-m", "ruff", "check", "."], cwd=PROJECT_ROOT, check=False
306+
)
278307
if lint.returncode != 0:
279308
raise typer.Exit(lint.returncode)
280309
tests = subprocess.run([sys.executable, "-m", "pytest", "-q"], cwd=PROJECT_ROOT, check=False)
@@ -285,8 +314,12 @@ def quality_check() -> None:
285314
def config_path() -> None:
286315
"""Print resolved Dewey config paths."""
287316
settings = get_settings()
288-
console.print(f"DEWEY config path: [cyan]{os.environ.get('XDG_CONFIG_HOME', '~/.config')}/dewey/config.yaml[/cyan]")
289-
console.print(f"TAPDB config path: [cyan]{settings.tapdb_config_path or os.environ.get('TAPDB_CONFIG_PATH', '')}[/cyan]")
317+
console.print(
318+
f"DEWEY config path: [cyan]{os.environ.get('XDG_CONFIG_HOME', '~/.config')}/dewey/config.yaml[/cyan]"
319+
)
320+
console.print(
321+
f"TAPDB config path: [cyan]{settings.tapdb_config_path or os.environ.get('TAPDB_CONFIG_PATH', '')}[/cyan]"
322+
)
290323

291324

292325
@config_app.command("show")

0 commit comments

Comments
 (0)