- Fix import in test_db_utils.py: use app.models instead of backend.app.models - Update health endpoint test to expect 'ok' status and infrastructure keys - Add CHANGELOG entries for PyPI proxy performance improvements
40 KiB
40 KiB
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
Added
- Added S3 bucket provisioning terraform configuration (#59)
- Creates an S3 bucket to be used for anything Orchard
- Creates a log bucket for any logs tracking the S3 bucket
- Added HTTP connection pooling infrastructure for improved PyPI proxy performance
HttpClientManagerwith configurable pool size, timeouts, and thread pool executor- Eliminates per-request connection overhead (~100-500ms → ~5ms)
- Added Redis caching layer with category-aware TTL for hermetic builds
CacheServicewith graceful fallback when Redis unavailable- Immutable data (artifact metadata, dependencies) cached forever
- Mutable data (package index, versions) uses configurable TTL
- Added
ArtifactRepositoryfor batch database operationsbatch_upsert_dependencies()reduces N+1 queries to single INSERTget_or_create_artifact()uses atomic ON CONFLICT upsert
- Added infrastructure status to health endpoint (
/health)- Reports HTTP pool size and worker threads
- Reports Redis cache connection status
- Added new configuration settings for HTTP client, Redis, and cache TTL
ORCHARD_HTTP_MAX_CONNECTIONS,ORCHARD_HTTP_CONNECT_TIMEOUT, etc.ORCHARD_REDIS_HOST,ORCHARD_REDIS_PORT,ORCHARD_REDIS_ENABLEDORCHARD_CACHE_TTL_INDEX,ORCHARD_CACHE_TTL_VERSIONS, etc.
- Added transparent PyPI proxy implementing PEP 503 Simple API (#108)
GET /pypi/simple/- package index (proxied from upstream)GET /pypi/simple/{package}/- version list with rewritten download linksGET /pypi/simple/{package}/{filename}- download with automatic caching- Allows
pip install --index-url https://orchard.../pypi/simple/ <package> - Artifacts cached on first access through configured upstream sources
- Added
POST /api/v1/cache/resolveendpoint to cache packages by coordinates instead of URL (#108)
Changed
- PyPI proxy now uses shared HTTP connection pool instead of per-request clients
- PyPI proxy now caches upstream source configuration in Redis
- Dependency storage now uses batch INSERT instead of individual queries
- Increased default database pool size from 5 to 20 connections
- Increased default database max overflow from 10 to 30 connections
- Enabled Redis in Helm chart values for dev, stage, and prod environments
- Upstream sources table text is now centered under column headers (#108)
- ENV badge now appears inline with source name instead of separate column (#108)
- Test and Edit buttons now have more prominent button styling (#108)
- Reduced footer padding for cleaner layout (#108)
Fixed
- Fixed purge_seed_data crash when deleting access permissions - was comparing UUID to VARCHAR column (#107)
Changed
- Upstream source connectivity test no longer follows redirects, fixing "Exceeded maximum allowed redirects" error with Artifactory proxies (#107)
- Test runs automatically after saving a new or updated upstream source (#107)
- Test status now shows as colored dots (green=success, red=error) instead of text badges (#107)
- Clicking red dot shows error details in a modal (#107)
- Source name column no longer wraps text for better table layout (#107)
- Renamed "Cache Management" page to "Upstream Sources" (#107)
- Moved Delete button from table row to edit modal for cleaner table layout (#107)
Removed
- Removed
is_publicfield from upstream sources - all sources are now treated as internal/private (#107) - Removed
allow_public_internet(air-gap mode) setting from cache settings - not needed for enterprise proxy use case (#107) - Removed seeding of public registry URLs (npm-public, pypi-public, maven-central, docker-hub) (#107)
- Removed "Public" badge and checkbox from upstream sources UI (#107)
- Removed "Allow Public Internet" toggle from cache settings UI (#107)
- Removed "Global Settings" section from cache management UI - auto-create system projects is always enabled (#107)
- Removed unused CacheSettings frontend types and API functions (#107)
Added
- Added
ORCHARD_PURGE_SEED_DATAenvironment variable support to stage helm values to remove seed data from long-running deployments (#107) - Added frontend system projects visual distinction (#105)
- "Cache" badge for system projects in project list
- "System Cache" badge on project detail page
- Added
is_systemfield to Project type
- Added frontend admin page for upstream sources and cache settings (#75)
- New
/admin/cachepage accessible from user menu (admin only) - Upstream sources table with create/edit/delete/test connectivity
- Cache settings section with air-gap mode and auto-create system projects toggles
- Visual indicators for env-defined sources (locked, cannot be modified)
- Environment variable override badges when settings are overridden
- API client functions for all cache admin operations
- New
- Added environment variable overrides for cache configuration (#74)
ORCHARD_CACHE_ALLOW_PUBLIC_INTERNET- Override allow_public_internet (air-gap mode)ORCHARD_CACHE_AUTO_CREATE_SYSTEM_PROJECTS- Override auto_create_system_projectsORCHARD_UPSTREAM__{NAME}__*- Define upstream sources via env vars- Env-defined sources appear in API with
source: "env"marker - Env-defined sources cannot be modified/deleted via API (400 error)
- Cache settings response includes
*_env_overridefields when overridden - 7 unit tests for env var parsing and configuration
- Added Global Cache Settings Admin API (#73)
GET /api/v1/admin/cache-settings- Retrieve current cache settingsPUT /api/v1/admin/cache-settings- Update cache settings (partial updates)- Admin-only access with audit logging
- Controls
allow_public_internet(air-gap mode) andauto_create_system_projects - 7 integration tests for settings management
- Added Upstream Sources Admin API for managing cache sources (#72)
GET /api/v1/admin/upstream-sources- List sources with filteringPOST /api/v1/admin/upstream-sources- Create source with auth configurationGET /api/v1/admin/upstream-sources/{id}- Get source detailsPUT /api/v1/admin/upstream-sources/{id}- Update source (partial updates)DELETE /api/v1/admin/upstream-sources/{id}- Delete sourcePOST /api/v1/admin/upstream-sources/{id}/test- Test connectivity- Admin-only access with audit logging
- Credentials never exposed (only has_password/has_headers flags)
- 13 integration tests for all CRUD operations
- Added system project restrictions and management (#71)
- System projects (
_npm,_pypi, etc.) cannot be deleted (returns 403) - System projects cannot be made private (must remain public)
GET /api/v1/system-projectsendpoint to list all system cache projects- 5 integration tests for system project restrictions
- System projects (
- Added Cache API endpoint for fetching and storing artifacts from upstream URLs (#70)
POST /api/v1/cacheendpoint to cache artifacts from upstream registries- URL parsing helpers to extract package name/version from npm, PyPI, Maven URLs
- Automatic system project creation (
_npm,_pypi,_maven, etc.) - URL-to-artifact provenance tracking via
cached_urlstable - Optional user project cross-referencing for custom organization
- Cache hit returns existing artifact without re-fetching
- Air-gap mode enforcement (blocks public URLs when disabled)
- Hash verification for downloaded artifacts
- 21 unit tests for URL parsing and cache endpoint
- Added HTTP client for fetching artifacts from upstream sources (#69)
UpstreamClientclass inbackend/app/upstream.pywith streaming downloads- SHA256 hash computation while streaming (doesn't load large files into memory)
- Auth support: none, basic auth, bearer token, API key (custom headers)
- URL-to-source matching by URL prefix with priority ordering
- Configuration options: timeouts, retries with exponential backoff, redirect limits, max file size
- Air-gap mode enforcement via
allow_public_internetsetting - Response header capture for provenance tracking
- Proper error handling with custom exception types
- Connection test method for upstream source validation
- 33 unit tests for client functionality
- Added upstream artifact caching schema for hermetic builds (#68)
upstream_sourcestable for configuring upstream registries (npm, PyPI, Maven, etc.)cache_settingstable for global settings including air-gap modecached_urlstable for URL-to-artifact provenance trackingis_systemcolumn on projects for system cache projects (_npm, _pypi, etc.)- Support for multiple auth types: none, basic auth, bearer token, API key
- Fernet encryption for credentials using
ORCHARD_CACHE_ENCRYPTION_KEY - Default upstream sources seeded (npm-public, pypi-public, maven-central, docker-hub) - disabled by default
- Migration
010_upstream_caching.sql
- Added team-based multi-tenancy for organizing projects and collaboration (#88-#104)
- Teams serve as organizational containers for projects
- Users can belong to multiple teams with different roles (owner, admin, member)
- Projects can optionally belong to a team
- Added database schema for teams (#88):
teamstable with id, name, slug, description, settings, timestampsteam_membershipstable mapping users to teams with rolesteam_idcolumn on projects table for team association- Migrations
009_teams.sqland009b_migrate_projects.sql
- Added Team and TeamMembership ORM models with relationships (#89)
- Added TeamAuthorizationService for team-level access control (#90):
- Team owner/admin gets admin access to all team projects
- Team member gets read access to team projects (upgradeable by explicit permission)
- Role hierarchy: owner > admin > member
- Added Team API endpoints (#92, #93, #94, #95):
GET /api/v1/teams- List teams user belongs to (paginated)POST /api/v1/teams- Create team (creator becomes owner)GET /api/v1/teams/{slug}- Get team detailsPUT /api/v1/teams/{slug}- Update team (requires admin)DELETE /api/v1/teams/{slug}- Delete team (requires owner)GET /api/v1/teams/{slug}/members- List team membersPOST /api/v1/teams/{slug}/members- Add member (requires admin)PUT /api/v1/teams/{slug}/members/{username}- Update member roleDELETE /api/v1/teams/{slug}/members/{username}- Remove memberGET /api/v1/teams/{slug}/projects- List team projects (paginated)
- Updated project creation to support optional team assignment (#95)
- Updated project responses to include team info (team_id, team_slug, team_name)
- Added frontend team management (#97-#104):
- TeamContext provider for managing current team selection
- TeamSelector dropdown component (persists selection in localStorage)
- Teams list page at
/teams - Team dashboard page at
/teams/{slug}with inline project creation - Team settings page at
/teams/{slug}/settings - Team members page at
/teams/{slug}/members - Teams navigation link in header (authenticated users only)
- Updated seed data to create a "Demo Team" and assign all seed projects to it
- Added TypeScript types and API client functions for teams
- Access management now shows team-based permissions alongside explicit permissions
- Team-based access displayed as read-only with "Source" column indicating origin
- Team members with access show team slug and role
- Added integration tests for team CRUD, membership, and project operations
- Redesigned teams portal with modern card-based layout
- Card grid view with team avatar, name, slug, role badge, and stats
- Stats bar showing total teams, owned teams, and total projects
- Search functionality for filtering teams (appears when >3 teams)
- Empty states for no teams and no search results
- Added user autocomplete component for team member invitations
GET /api/v1/users/searchendpoint for username prefix search- Dropdown shows matching users as you type
- Keyboard navigation support (arrow keys, enter, escape)
- Debounced search to reduce API calls
- Added unit tests for TeamAuthorizationService
- Added
ORCHARD_ADMIN_PASSWORDenvironment variable to configure initial admin password (#87)- When set, admin user is created with the specified password (no password change required)
- When not set, defaults to
changeme123and requires password change on first login
- Added Helm chart support for admin password via multiple sources (#87):
orchard.auth.adminPassword- plain value (creates K8s secret)orchard.auth.existingSecret- reference existing K8s secretorchard.auth.secretsManager- AWS Secrets Manager integration
- Added
.env.exampletemplate for local development (#87) - Added
.envfile support in docker-compose.local.yml (#87) - Added Project Settings page accessible to project admins (#65)
- General settings section for editing description and visibility
- Access Management section (moved from project page)
- Danger Zone section with inline delete confirmation requiring project name
- Settings button (gear icon) on project page header for admins
- Added artifact dependency management system (#76, #77, #78, #79, #80, #81)
artifact_dependenciestable with version/tag constraints and check constraintsArtifactDependencySQLAlchemy model with indexes for fast lookups- Ensure file parsing (
orchard.ensureYAML format) during artifact upload - Circular dependency detection at upload time (rejected with 400)
- Dependency conflict detection at resolution time (409 with conflict details)
- Added dependency API endpoints (#78, #79):
GET /api/v1/artifact/{artifact_id}/dependencies- Get dependencies by artifact IDGET /api/v1/project/{project}/{package}/+/{ref}/dependencies- Get dependencies by refGET /api/v1/project/{project}/{package}/reverse-dependencies- Get reverse dependencies (paginated)GET /api/v1/project/{project}/{package}/+/{ref}/resolve- Resolve full dependency tree
- Added dependency resolution with topological sorting (#79)
- Returns flat list of all artifacts needed in dependency order
- Includes download URLs, sizes, and version info for each artifact
- Added frontend dependency visualization (#84, #85, #86):
- Dependencies section on package page showing direct dependencies for selected tag
- Tag/version selector to switch between artifacts
- "Used By" section showing reverse dependencies with pagination
- Interactive dependency graph modal with:
- Tree visualization with collapsible nodes
- Zoom (mouse wheel + buttons) and pan (click-drag)
- Click to navigate to package
- Hover tooltip with package details
- Error display for circular dependencies and conflicts
- Added migration
008_artifact_dependencies.sqlfor dependency schema - Added
dependencies.pymodule with parsing, validation, and resolution logic - Added comprehensive integration tests for all dependency features
Changed
- Added pre-test stage reset to ensure known environment state before integration tests (#54)
- Upload endpoint now accepts optional
ensurefile parameter for declaring dependencies - Updated upload API documentation with ensure file format and examples
- Converted teams list and team projects to use DataTable component for consistent styling
- Centered team members and team settings page content
- Added orchard logo icon and dot separator to footer
Fixed
- Fixed dark theme styling for team pages - modals, forms, and dropdowns now use correct theme variables
- Fixed UserAutocomplete and TeamSelector dropdown backgrounds for dark theme
[0.5.1] - 2026-01-23
Changed
- Simplified tag pipeline to only run deploy and smoke tests (image already built on main) (#54)
Fixed
- Fixed production CI deployment namespace to use correct
orch-namespace(#54) - Added gitleaks config to allowlist test files from secret scanning (#54)
[0.5.0] - 2026-01-23
Added
- Added factory reset endpoint
POST /api/v1/admin/factory-resetfor test environment cleanup (#54)- Requires admin authentication and
X-Confirm-Reset: yes-delete-all-dataheader - Drops all database tables, clears S3 bucket, reinitializes schema, re-seeds default data
- CI pipeline automatically calls this after integration tests on stage
- Requires admin authentication and
- Added
delete_all()method to storage backend for bulk S3 object deletion (#54) - Added AWS Secrets Manager CSI driver support for database credentials (#54)
- Added SecretProviderClass template for Secrets Manager integration (#54)
- Added IRSA service account annotations for prod and stage environments (#54)
- Added comprehensive upload/download tests for size boundaries (1B to 1GB) (#38)
- Added concurrent upload/download tests (2, 5, 10 parallel operations) (#38)
- Added data integrity tests (binary, text, unicode, compressed content) (#38)
- Added chunk boundary tests for edge cases (#38)
- Added
@pytest.mark.largeand@pytest.mark.concurrenttest markers (#38) - Added
generate_content()andgenerate_content_with_hash()test helpers (#38) - Added
sized_contentfixture for generating test content of specific sizes (#38) - Added upload API tests: upload without tag, artifact creation verification, S3 object creation (#38)
- Added download API tests: tag: prefix resolution, 404 for nonexistent project/package/artifact (#38)
- Added download header tests: Content-Type, Content-Length, Content-Disposition, ETag, X-Checksum-SHA256 (#38)
- Added error handling tests: timeout behavior, checksum validation, resource cleanup, graceful error responses (#38)
- Added version API tests: version creation, auto-detection, listing, download by version prefix (#38)
- Added integrity verification tests: round-trip hash verification, client-side verification workflow, size variants (1KB-10MB) (#40)
- Added consistency check endpoint tests with response format validation (#40)
- Added corruption detection tests: bit flip, truncation, appended content, size mismatch, missing S3 objects (#40)
- Added Digest header tests (RFC 3230) and verification mode tests (#40)
- Added integrity verification documentation (
docs/integrity-verification.md) (#40) - Added conditional request support for downloads (If-None-Match, If-Modified-Since) returning 304 Not Modified (#42)
- Added caching headers to downloads: Cache-Control (immutable), Last-Modified (#42)
- Added 416 Range Not Satisfiable response for invalid range requests (#42)
- Added download completion logging with bytes transferred and throughput (#42)
- Added client disconnect handling during streaming downloads (#42)
- Added streaming download tests: range requests, conditional requests, caching headers, download resume (#42)
- Added upload duration and throughput metrics (
duration_ms,throughput_mbps) to upload response (#43) - Added upload progress logging for large files (hash computation and multipart upload phases) (#43)
- Added client disconnect handling during uploads with proper cleanup (#43)
- Added upload progress tracking endpoint
GET /upload/{upload_id}/progressfor resumable uploads (#43) - Added large file upload tests (10MB, 100MB, 1GB) with multipart upload verification (#43)
- Added upload cancellation and timeout handling tests (#43)
- Added comprehensive API documentation for upload endpoints with curl, Python, and JavaScript examples (#43)
- Added
package_versionstable for immutable version tracking separate from mutable tags (#56)- Versions are set at upload time via explicit
versionparameter or auto-detected from filename/metadata - Version detection priority: explicit parameter > package metadata > filename pattern
- Versions are immutable once created (unlike tags which can be moved)
- Versions are set at upload time via explicit
- Added version API endpoints (#56):
GET /api/v1/project/{project}/{package}/versions- List all versions for a packageGET /api/v1/project/{project}/{package}/versions/{version}- Get specific version detailsDELETE /api/v1/project/{project}/{package}/versions/{version}- Delete a version (admin only)
- Added version support to upload endpoint via
versionform parameter (#56) - Added
version:X.Y.Zprefix for explicit version resolution in download refs (#56) - Added version field to tag responses (shows which version the artifact has, if any) (#56)
- Added migration
007_package_versions.sqlwith ref_count triggers and data migration from semver tags (#56) - Added production deployment job triggered by semantic version tags (v1.0.0) with manual approval gate (#63)
- Added production Helm values file with persistence enabled (20Gi PostgreSQL, 100Gi MinIO) (#63)
- Added integration tests for production deployment (#63)
- Added GitLab CI pipeline for feature branch deployments to dev namespace (#51)
- Added
deploy_featurejob with dynamic hostnames and unique release names (#51) - Added
cleanup_featurejob withon_stopfor automatic cleanup on merge (#51) - Added
values-dev.yamlHelm values for lightweight ephemeral environments (#51) - Added main branch deployment to stage environment (#51)
- Added post-deployment integration tests (#51)
- Added internal proxy configuration for npm, pip, helm, and apt (#51)
Changed
- Configured stage and prod to use AWS RDS instead of PostgreSQL subchart (#54)
- Configured stage and prod to use AWS S3 instead of MinIO subchart (#54)
- Changed prod deployment from manual to automatic on version tags (#54)
- Updated S3 client to support IRSA credentials when no explicit keys provided (#54)
- Changed prod image pullPolicy to Always (#54)
- Added proxy-body-size annotation to prod ingress for large uploads (#54)
- CI integration tests now run full pytest suite (~350 tests) against deployed environment instead of 3 smoke tests
- CI production deployment uses lightweight smoke tests only (no test data creation in prod)
- CI pipeline improvements: shared pip cache,
interruptibleflag on test jobs, retry on integration tests - Simplified deploy verification to health check only (full checks done by integration tests)
- Extracted environment URLs to global variables for maintainability
- Made
cleanup_featurejob standalone (no longer inherits deploy template dependencies) - Renamed
integration_test_prodtosmoke_test_prodfor clarity - Updated download ref resolution to check versions before tags (version → tag → artifact ID) (#56)
- Deploy jobs now require all security scans to pass before deployment (added test_image, app_deps_scan, cve_scan, cve_sbom_analysis, app_sbom_analysis to dependencies) (#63)
- Increased deploy job timeout from 5m to 10m (#63)
- Added
--atomicflag to Helm deployments for automatic rollback on failure - Adjusted dark mode color palette to use lighter background tones for better readability and reduced eye strain (#52)
- Replaced project card grid with sortable data table on Home page for better handling of large project lists
- Replaced package card grid with sortable data table on Project page for consistency
- Replaced SortDropdown with table header sorting on Package page for consistency
- Enabled sorting on supported table columns (name, created, updated) via clickable headers
- Updated browser tab title to "Orchard" with custom favicon
- Improved pod naming: Orchard pods now named
orchard-{env}-server-*for clarity (#51)
Fixed
- Fixed factory reset not creating default admin user after reset (#60)
- Admin user was only created at server startup, not after factory reset
- CI reset job would fail to login because admin user didn't exist
- Improved reset_stage CI job reliability (#60)
- Added application-level retry logic (3 attempts with 5s delay)
- Added job-level retry for transient failures
- Fixed httpx client to use proper context manager
- Increased timeout to 120s for reset operations
- Fixed CI integration test rate limiting: added configurable
ORCHARD_LOGIN_RATE_LIMITenv var, relaxed to 1000/minute for dev/stage - Fixed duplicate
TestSecurityEdgeCasesclass definition in test_auth_api.py - Fixed integration tests auth: session-scoped client, configurable credentials via env vars, fail-fast on auth errors
- Fixed 413 Request Entity Too Large errors on uploads by adding
proxy-body-size: "0"nginx annotation to Orchard ingress - Fixed CI tests that require direct S3 access: added
@pytest.mark.requires_direct_s3marker and excluded from CI - Fixed ref_count triggers not being created: added auto-migration for tags ref_count trigger functions
- Fixed Content-Disposition header encoding for non-ASCII filenames using RFC 5987 (#38)
- Fixed deploy jobs running even when tests or security scans fail (changed rules from
when: alwaystowhen: on_success) (#63) - Fixed python_tests job not using internal PyPI proxy (#63)
- Fixed
cleanup_featurejob failing when branch is deleted (GIT_STRATEGY: none) (#51) - Fixed gitleaks false positives with fingerprints for historical commits (#51)
- Fixed integration tests running when deploy fails (
when: on_success) (#51) - Fixed static file serving for favicon and other files in frontend dist root
- Fixed deploy jobs running when secrets scan fails (added
secretsto deploy dependencies) - Fixed dev environment memory requests to equal limits per cluster Kyverno policy
- Fixed init containers missing resource limits (Kyverno policy compliance)
- Fixed Python SyntaxWarning for invalid escape sequence in database migration regex pattern
Removed
- Removed unused
store_streaming()method from storage.py (#51) - Disabled PostgreSQL subchart for stage and prod environments (#54)
- Disabled MinIO subchart for stage and prod environments (#54)
[0.4.0] - 2026-01-12
Added
- Added user authentication system with session-based login (#50)
userstable with password hashing (bcrypt), admin flag, active statussessionstable for web login sessions (24-hour expiry)auth_settingstable for future OIDC configuration- Default admin user created on first boot (username: admin, password: admin)
- Added auth API endpoints (#50)
POST /api/v1/auth/login- Login with username/passwordPOST /api/v1/auth/logout- Logout and clear sessionGET /api/v1/auth/me- Get current user infoPOST /api/v1/auth/change-password- Change own password
- Added API key management with user ownership (#50)
POST /api/v1/auth/keys- Create API key (format:orch_<random>)GET /api/v1/auth/keys- List user's API keysDELETE /api/v1/auth/keys/{id}- Revoke API key- Added
owner_id,scopes,descriptioncolumns toapi_keystable
- Added admin user management endpoints (#50)
GET /api/v1/admin/users- List all usersPOST /api/v1/admin/users- Create userGET /api/v1/admin/users/{username}- Get user detailsPUT /api/v1/admin/users/{username}- Update user (admin/active status)POST /api/v1/admin/users/{username}/reset-password- Reset password
- Added
auth.pymodule with AuthService class and FastAPI dependencies (#50) - Added auth schemas: LoginRequest, LoginResponse, UserResponse, APIKeyResponse (#50)
- Added migration
006_auth_tables.sqlfor auth database tables (#50) - Added frontend Login page with session management (#50)
- Added frontend API Keys management page (#50)
- Added frontend Admin Users page (admin-only) (#50)
- Added AuthContext for frontend session state (#50)
- Added user menu to Layout header with login/logout (#50)
- Added 15 integration tests for auth system (#50)
- Added reusable
DragDropUploadcomponent for artifact uploads (#8)- Drag-and-drop file selection with visual feedback
- Click-to-browse fallback
- Multiple file upload support with queue management
- Real-time progress indicators with speed and ETA
- File type and size validation (configurable)
- Concurrent upload handling (configurable max concurrent)
- Automatic retry with exponential backoff for network errors
- Individual file status (pending, uploading, complete, failed)
- Retry and remove actions per file
- Auto-dismiss success messages after 5 seconds
- Integrated DragDropUpload into PackagePage replacing basic file input (#8)
- Added frontend testing infrastructure with Vitest and React Testing Library (#14)
- Configured Vitest for React/TypeScript with jsdom
- Added 24 unit tests for DragDropUpload component
- Tests cover: rendering, drag-drop events, file validation, upload queue, progress, errors
- Added chunked upload support for large files (#9)
- Files >100MB automatically use chunked upload API (10MB chunks)
- Client-side SHA256 hash computation via Web Crypto API
- localStorage persistence for resume after browser close
- Deduplication check at upload init phase
- Added offline detection and network resilience (#12)
- Automatic pause when browser goes offline
- Auto-resume when connection restored
- Offline banner UI with status message
- XHR abort on network loss to prevent hung requests
- Added download by artifact ID feature (#10)
- Direct artifact ID input field on package page
- Hex-only input validation with character count
- File size and filename displayed in tag list
- Added backend security tests (#15)
- Path traversal prevention tests for upload/download
- Malformed request handling tests
- Checksum validation tests
- 10 new security-focused integration tests
- Added download verification with
verifyandverify_modequery parameters (#26)?verify=true&verify_mode=pre- Pre-verification: verify before streaming (guaranteed no corrupt data)?verify=true&verify_mode=stream- Streaming verification: verify while streaming (logs error if mismatch)
- Added checksum response headers to all download endpoints (#27)
X-Checksum-SHA256- SHA256 hash of the artifactX-Content-Length- File size in bytesX-Checksum-MD5- MD5 hash (if available)ETag- Artifact ID (SHA256)Digest- RFC 3230 format sha-256 hash (base64)X-Verified- Verification status (true/false/pending)
- Added
checksum.pymodule with SHA256 utilities (#26)compute_sha256()andcompute_sha256_stream()functionsHashingStreamWrapperfor incremental hash computationVerifyingStreamWrapperfor stream verificationverify_checksum()andverify_checksum_strict()functionsChecksumMismatchErrorexception with context
- Added
get_verified()andget_stream_verified()methods to storage layer (#26) - Added
logging_config.pymodule with structured logging (#28)- JSON logging format for production
- Request ID tracking via context variables
- Verification failure logging with full context
- Added
log_levelandlog_formatsettings to configuration (#28) - Added 62 unit tests for checksum utilities and verification (#29)
- Added 17 integration tests for download verification API (#29)
- Added global artifacts endpoint
GET /api/v1/artifactswith project/package/tag/size/date filters (#18) - Added global tags endpoint
GET /api/v1/tagswith project/package/search/date filters (#18) - Added wildcard pattern matching (
*) for tag filters across all endpoints (#18) - Added comma-separated multi-value support for tag filters (#18)
- Added
searchparameter to/api/v1/uploadsfor filename search (#18) - Added
tagfilter to/api/v1/uploadsendpoint (#18) - Added
sortandorderparameters to/api/v1/uploadsendpoint (#18) - Added
min_sizeandmax_sizefilters to package artifacts endpoint (#18) - Added
sortandorderparameters to package artifacts endpoint (#18) - Added
fromandtodate filters to package tags endpoint (#18) - Added
GlobalArtifactResponseandGlobalTagResponseschemas (#18) - Added S3 object verification before database commit during upload (#19)
- Added S3 object cleanup on database commit failure (#19)
- Added upload duration tracking (
duration_msfield) (#19) - Added
User-Agentheader capture during uploads (#19) - Added
X-Checksum-SHA256header support for client-side checksum verification (#19) - Added
status,error_message,client_checksumcolumns to uploads table (#19) - Added
upload_lockstable for future concurrent upload conflict detection (#19) - Added consistency check endpoint
GET /api/v1/admin/consistency-check(#19) - Added
PUT /api/v1/projects/{project}endpoint for project updates with audit logging (#20) - Added
PUT /api/v1/project/{project}/packages/{package}endpoint for package updates with audit logging (#20) - Added
artifact.downloadaudit logging to download endpoint (#20) - Added
ProjectHistoryandPackageHistorymodels with database triggers (#20) - Added migration
004_history_tables.sqlfor project/package history (#20) - Added migration
005_upload_enhancements.sqlfor upload status tracking (#19) - Added 9 integration tests for global artifacts/tags endpoints (#18)
- Added global uploads query endpoint
GET /api/v1/uploadswith project/package/user/date filters (#18) - Added project-level uploads endpoint
GET /api/v1/project/{project}/uploads(#18) - Added
has_morefield to pagination metadata for easier pagination UI (#18) - Added
upload_id,content_type,original_name,created_atfields to upload response (#19) - Added audit log API endpoints with filtering and pagination (#20)
GET /api/v1/audit-logs- list all audit logs with action/resource/user/date filtersGET /api/v1/projects/{project}/audit-logs- project-scoped audit logsGET /api/v1/project/{project}/{package}/audit-logs- package-scoped audit logs
- Added upload history API endpoints (#20)
GET /api/v1/project/{project}/{package}/uploads- list upload events for a packageGET /api/v1/artifact/{id}/uploads- list all uploads of a specific artifact
- Added artifact provenance endpoint
GET /api/v1/artifact/{id}/history(#20)- Returns full artifact history including packages, tags, and upload events
- Added audit logging for project.create, package.create, tag.create, tag.update, artifact.upload actions (#20)
- Added
AuditLogResponse,UploadHistoryResponse,ArtifactProvenanceResponseschemas (#20) - Added
TagHistoryDetailResponseschema with artifact metadata (#20) - Added 31 integration tests for audit log, history, and upload query endpoints (#22)
Changed
- Standardized audit action naming to
{entity}.{action}pattern (project.delete, package.delete, tag.delete) (#20) - Added
StorageBackendprotocol/interface for backend-agnostic storage (#33) - Added
health_check()method to storage backend with/healthendpoint integration (#33) - Added
verify_integrity()method for post-upload hash validation (#33) - Added S3 configuration options:
s3_verify_ssl,s3_connect_timeout,s3_read_timeout,s3_max_retries(#33) - Added
S3StorageUnavailableErrorandHashCollisionErrorexception types (#33) - Added hash collision detection by comparing file sizes during deduplication (#33)
- Added garbage collection endpoint
POST /api/v1/admin/garbage-collectfor orphaned artifacts (#36) - Added orphaned artifacts listing endpoint
GET /api/v1/admin/orphaned-artifacts(#36) - Added global storage statistics endpoint
GET /api/v1/stats(#34) - Added storage breakdown endpoint
GET /api/v1/stats/storage(#34) - Added deduplication metrics endpoint
GET /api/v1/stats/deduplication(#34) - Added per-project statistics endpoint
GET /api/v1/projects/{project}/stats(#34) - Added per-package statistics endpoint
GET /api/v1/project/{project}/packages/{package}/stats(#34) - Added per-artifact statistics endpoint
GET /api/v1/artifact/{id}/stats(#34) - Added cross-project deduplication endpoint
GET /api/v1/stats/cross-project(#34) - Added timeline statistics endpoint
GET /api/v1/stats/timelinewith daily/weekly/monthly periods (#34) - Added stats export endpoint
GET /api/v1/stats/exportwith JSON/CSV formats (#34) - Added summary report endpoint
GET /api/v1/stats/reportwith markdown/JSON formats (#34) - Added Dashboard page at
/dashboardwith storage and deduplication visualizations (#34) - Added pytest infrastructure with mock S3 client for unit testing (#35)
- Added unit tests for SHA256 hash calculation (#35)
- Added unit tests for duplicate detection and deduplication behavior (#35)
- Added integration tests for upload scenarios and ref_count management (#35)
- Added integration tests for S3 verification and failure cleanup (#35)
- Added integration tests for all stats endpoints (#35)
- Added integration tests for cascade deletion ref_count behavior (package/project delete) (#35)
- Added integration tests for tag update ref_count adjustments (#35)
- Added integration tests for garbage collection endpoints (#35)
- Added integration tests for file size validation (#35)
- Added test dependencies to requirements.txt (pytest, pytest-asyncio, pytest-cov, httpx, moto) (#35)
- Added
ORCHARD_MAX_FILE_SIZEconfig option (default: 10GB) for upload size limits (#37) - Added
ORCHARD_MIN_FILE_SIZEconfig option (default: 1 byte, rejects empty files) (#37) - Added file size validation to upload and resumable upload endpoints (#37)
- Added comprehensive deduplication design document (
docs/design/deduplication-design.md) (#37)
Fixed
- Fixed Helm chart
minio.ingressconflicting with Bitnami MinIO subchart by renaming tominioIngress(#48) - Fixed JSON report serialization error for Decimal types in
GET /api/v1/stats/report(#34) - Fixed resumable upload double-counting ref_count when tag provided (removed manual increment, SQL triggers handle it) (#35)
[0.3.0] - 2025-12-15
Changed
- Changed default download mode from
proxytopresignedfor better performance (#48)
Added
- Added presigned URL support for direct S3 downloads (#48)
- Added
ORCHARD_DOWNLOAD_MODEconfig option (presigned,redirect,proxy) (#48) - Added
ORCHARD_PRESIGNED_URL_EXPIRYconfig option (default: 3600 seconds) (#48) - Added
?mode=query parameter to override download mode per-request (#48) - Added
/api/v1/project/{project}/{package}/+/{ref}/urlendpoint for getting presigned URLs (#48) - Added
PresignedUrlResponseschema with URL, expiry, checksums, and artifact metadata (#48) - Added MinIO ingress support in Helm chart for presigned URL access (#48)
- Added
orchard.download.modeandorchard.download.presignedUrlExpiryHelm values (#48) - Added integrity verification workflow design document (#24)
- Added
sha256field to API responses for clarity (alias ofid) (#25) - Added
checksum_sha1field to artifacts table for compatibility (#25) - Added
s3_etagfield to artifacts table for S3 verification (#25) - Compute and store MD5, SHA1, and S3 ETag alongside SHA256 during upload (#25)
- Added
Dockerfile.localanddocker-compose.local.ymlfor local development (#25) - Added migration script
003_checksum_fields.sqlfor existing databases (#25)
[0.2.0] - 2025-12-15
Added
- Added
formatandplatformfields to packages table (#16) - Added
checksum_md5andmetadataJSONB fields to artifacts table (#16) - Added
updated_atfield to tags table (#16) - Added
tag_name,user_agent,duration_ms,deduplicated,checksum_verifiedfields to uploads table (#16) - Added
change_typefield to tag_history table (#16) - Added composite indexes for common query patterns (#16)
- Added GIN indexes on JSONB fields for efficient JSON queries (#16)
- Added partial index for public projects (#16)
- Added database triggers for
updated_attimestamps (#16) - Added database triggers for maintaining artifact
ref_countaccuracy (#16) - Added CHECK constraints for data integrity (
size > 0,ref_count >= 0) (#16) - Added migration script
002_schema_enhancements.sqlfor existing databases (#16)
Changed
- Updated images to use internal container BSF proxy (#46)
[0.1.0] - 2025-12-12
Added
- Added Prosper docker template config (#45)
Changed
- Changed the Dockerfile npm build arg to use the deps.global.bsf.tools URL as the default registry (#45)