generated from coulomb/repo-seed
WP-0001-T001: service scaffold (Python, FastAPI, uv, ruff, mypy, pytest)
Lands the smallest credible foundation per ADR-0005:
- pyproject.toml: hatchling build, runtime deps (FastAPI, uvicorn, SQLAlchemy 2.0,
asyncpg, aiosqlite, alembic, blake3, cbor2, typer, structlog, pydantic,
pydantic-settings); dev deps (pytest, pytest-asyncio, httpx, hypothesis, ruff,
mypy); ruff + mypy --strict + pytest configured.
- uv.lock committed.
- Makefile thin shims: install / dev / test / lint / format / type / migrate / clean.
- src/artifactstore/ package skeleton with placeholder __init__.py per concern:
identity, manifest, events, retention, audit, storage, dataplane, registry,
api/http (minimal FastAPI app, GET / scaffold banner), cli (typer app with
version subcommand), config (pydantic-settings).
- tests/{unit,integration}/conftest.py present; unit smoke tests assert package
imports, HTTP root route, CLI version round-trip, settings defaults.
- .env.example documents ARTIFACTSTORE_DATABASE_URL,
ARTIFACTSTORE_STORAGE_LOCAL_ROOT, ARTIFACTSTORE_LOG_LEVEL.
- README updated with install / dev / test instructions.
- .gitignore: claude local state, local runtime data (var/, sqlite db).
make lint && make type && make test pass on a clean checkout (4 tests, 20
source files type-clean under mypy --strict).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
8
src/artifactstore/__init__.py
Normal file
8
src/artifactstore/__init__.py
Normal file
@@ -0,0 +1,8 @@
|
||||
"""artifact-store: generic artifact registry and storage gateway.
|
||||
|
||||
The top-level package re-exports nothing yet. Submodules are documented in
|
||||
``docs/ARCHITECTURE-BLUEPRINT.md`` and each carries its own placeholder for
|
||||
the implementation tasks in workplan ARTIFACT-STORE-WP-0001.
|
||||
"""
|
||||
|
||||
__version__ = "0.1.0"
|
||||
4
src/artifactstore/api/__init__.py
Normal file
4
src/artifactstore/api/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
"""HTTP and future RPC API surfaces.
|
||||
|
||||
Submodules: :mod:`artifactstore.api.http`.
|
||||
"""
|
||||
24
src/artifactstore/api/http/__init__.py
Normal file
24
src/artifactstore/api/http/__init__.py
Normal file
@@ -0,0 +1,24 @@
|
||||
"""FastAPI application entry point.
|
||||
|
||||
The full registry-aware ``/health`` endpoint lands in
|
||||
ARTIFACT-STORE-WP-0001-T014. This scaffold exposes a minimal root route so
|
||||
``make dev`` has something to serve while the registry layer is being built.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
from artifactstore import __version__
|
||||
|
||||
app = FastAPI(title="artifact-store", version=__version__)
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def root() -> dict[str, str]:
|
||||
"""Return a service banner indicating the scaffold is up."""
|
||||
return {
|
||||
"service": "artifact-store",
|
||||
"version": __version__,
|
||||
"status": "scaffold",
|
||||
}
|
||||
5
src/artifactstore/audit/__init__.py
Normal file
5
src/artifactstore/audit/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
"""Audit surface over the event log.
|
||||
|
||||
Audit is a view over :mod:`artifactstore.events` filtered to access and
|
||||
lifecycle event types; it has no separate write path.
|
||||
"""
|
||||
36
src/artifactstore/cli/__init__.py
Normal file
36
src/artifactstore/cli/__init__.py
Normal file
@@ -0,0 +1,36 @@
|
||||
"""artifact-store command-line interface.
|
||||
|
||||
The CLI is a thin consumer of :mod:`artifactstore.registry` (per ADR-0005).
|
||||
The scaffold exposes only ``version``; richer subcommands land in later
|
||||
tasks of ARTIFACT-STORE-WP-0001 and follow-on workplans.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import typer
|
||||
|
||||
from artifactstore import __version__
|
||||
|
||||
app = typer.Typer(
|
||||
help="artifact-store: artifact registry and storage gateway",
|
||||
no_args_is_help=True,
|
||||
)
|
||||
|
||||
|
||||
@app.callback()
|
||||
def main() -> None:
|
||||
"""Top-level CLI entry point.
|
||||
|
||||
Forces typer into multi-command mode so subcommands behave consistently
|
||||
even while the scaffold only ships ``version``.
|
||||
"""
|
||||
|
||||
|
||||
@app.command()
|
||||
def version() -> None:
|
||||
"""Print the artifactstore version and exit."""
|
||||
typer.echo(__version__)
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
app()
|
||||
30
src/artifactstore/config.py
Normal file
30
src/artifactstore/config.py
Normal file
@@ -0,0 +1,30 @@
|
||||
"""Application configuration loaded from environment variables.
|
||||
|
||||
All settings are read from environment variables prefixed with
|
||||
``ARTIFACTSTORE_``. A ``.env`` file at the repository root is honoured for
|
||||
local development; see ``.env.example``.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
"""Top-level service configuration."""
|
||||
|
||||
model_config = SettingsConfigDict(
|
||||
env_prefix="ARTIFACTSTORE_",
|
||||
env_file=".env",
|
||||
env_file_encoding="utf-8",
|
||||
extra="ignore",
|
||||
)
|
||||
|
||||
database_url: str = "sqlite+aiosqlite:///./var/artifactstore.db"
|
||||
storage_local_root: str = "./var/storage"
|
||||
log_level: str = "INFO"
|
||||
|
||||
|
||||
def get_settings() -> Settings:
|
||||
"""Return a freshly-loaded :class:`Settings` instance."""
|
||||
return Settings()
|
||||
5
src/artifactstore/dataplane/__init__.py
Normal file
5
src/artifactstore/dataplane/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
"""Data plane SPI and in-process implementation.
|
||||
|
||||
The SPI lands in ARTIFACT-STORE-WP-0001-T012. See ADR-0004 for the
|
||||
control-plane / data-plane contract that this module isolates.
|
||||
"""
|
||||
5
src/artifactstore/events/__init__.py
Normal file
5
src/artifactstore/events/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
"""Append-only event log and materialised-view replayer.
|
||||
|
||||
Real implementation lands in ARTIFACT-STORE-WP-0001-T011. See ADR-0002 for
|
||||
the event-log-as-source-of-truth contract.
|
||||
"""
|
||||
5
src/artifactstore/identity/__init__.py
Normal file
5
src/artifactstore/identity/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
"""Content addresses and digest abstraction.
|
||||
|
||||
Real implementation lands in ARTIFACT-STORE-WP-0001-T009. See ADR-0001 for
|
||||
the dual-digest contract (BLAKE3 primary, SHA-256 retained for interop).
|
||||
"""
|
||||
5
src/artifactstore/manifest/__init__.py
Normal file
5
src/artifactstore/manifest/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
"""Package manifest model and canonical-CBOR codec.
|
||||
|
||||
Real implementation lands in ARTIFACT-STORE-WP-0001-T010. See ADR-0003 for
|
||||
the canonicalisation pin (RFC 8949 §4.2.2).
|
||||
"""
|
||||
6
src/artifactstore/registry/__init__.py
Normal file
6
src/artifactstore/registry/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
||||
"""Registry orchestrator.
|
||||
|
||||
Real implementation lands in ARTIFACT-STORE-WP-0001-T013. The orchestrator
|
||||
combines identity, manifest, events, retention, and dataplane into the
|
||||
operations exposed by the HTTP API and CLI.
|
||||
"""
|
||||
5
src/artifactstore/retention/__init__.py
Normal file
5
src/artifactstore/retention/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
"""Retention policy engine.
|
||||
|
||||
Seed classes land in ARTIFACT-STORE-WP-0001-T002 (data model). Active policy
|
||||
operations (extensions, holds, sweeper) land in workplan WP-0003.
|
||||
"""
|
||||
5
src/artifactstore/storage/__init__.py
Normal file
5
src/artifactstore/storage/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
"""Storage adapter SPI and backend registry.
|
||||
|
||||
The SPI and local filesystem backend land in ARTIFACT-STORE-WP-0001-T003.
|
||||
The S3-compatible backend lands in workplan WP-0004.
|
||||
"""
|
||||
Reference in New Issue
Block a user