# Task I: Storage Abstraction and Approved Artifact Lifecycle ## 1. Files Added - `src/features/foundation/storage/types.ts` - `src/features/foundation/storage/service.ts` - `src/features/foundation/storage/server/local-provider.ts` - `src/features/foundation/storage/server/s3-provider.ts` - `src/features/foundation/storage/server/provider.ts` - `src/features/foundation/storage/server/checksum.ts` - `src/features/foundation/document-artifact/server/service.ts` - `src/app/api/crm/document-artifacts/[id]/download/route.ts` - `drizzle/0009_lazy_shard.sql` - `drizzle/meta/0009_snapshot.json` ## 2. Files Modified - `package.json` - `package-lock.json` - `src/db/schema.ts` - `src/lib/auth/rbac.ts` - `src/features/foundation/pdf-generator/server/service.ts` - `src/features/foundation/approval/server/service.ts` - `src/features/crm/quotations/api/types.ts` - `src/features/crm/quotations/server/service.ts` - `src/features/crm/quotations/components/quotation-detail.tsx` - `src/app/api/crm/quotations/[id]/approved-pdf/route.ts` - `scripts/seed-task-h1-fixture.js` - `docs/implementation/technical-debt.md` - `docs/adr/0009-approved-document-storage-lifecycle.md` ## 3. Storage Provider Added Added a storage foundation under `src/features/foundation/storage/**`. Providers: - local provider for development - S3 / MinIO-compatible provider for production-oriented storage Configuration supported: - `STORAGE_PROVIDER` - `LOCAL_STORAGE_ROOT` - `S3_ENDPOINT` - `S3_REGION` - `S3_BUCKET` - `S3_ACCESS_KEY_ID` - `S3_SECRET_ACCESS_KEY` - `S3_FORCE_PATH_STYLE` ## 4. Artifact Schema Added Added `crm_document_artifacts` with: - organization/entity identity - document and artifact types - template version reference - storage provider and storage key - file metadata - checksum - lifecycle status - generated / locked / voided metadata - JSON metadata payload Added `approved_artifact_id` to `crm_quotations`. ## 5. Approved PDF Refactor Approved quotation PDFs now: - write through `StorageProvider.putObject()` - persist checksum via SHA-256 - create a `crm_document_artifacts` row - lock the artifact after generation - update quotation `approvedArtifactId` - keep `approvedPdfUrl` as compatibility reference in `artifact:` form Rules enforced: - only approved quotations can generate approved PDF - locked approved artifacts cannot be overwritten - existing active approved artifact blocks silent regeneration ## 6. Secure Download Added Added secure artifact route: - `GET /api/crm/document-artifacts/[id]/download` Updated quotation approved-PDF flow so secure reads resolve artifact metadata from the database and fetch bytes through the storage provider instead of treating public file paths as source of truth. ## 7. UI Updated Quotation detail now shows approved artifact metadata when available: - file name - generated by - generated at - checksum short form - locked status badge It also shows a legacy warning when a quotation still references old `/generated/...` storage without an artifact record. ## 8. Permissions Added - `crm.document_artifact.read` - `crm.document_artifact.download` - `crm.document_artifact.void` Defaults were added alongside the existing quotation PDF permissions in RBAC role derivation. ## 9. Audit Integration Artifact service now audits: - `create` - `lock` - `void` - `download` Entity type: - `crm_document_artifact` ## 10. Compatibility Notes Compatibility behavior now supports: - `approvedArtifactId` when present - `approvedPdfUrl = artifact:` during migration - legacy `/generated/...` approved PDF paths with warning fallback Task I intentionally does not bulk-migrate legacy files yet. ## 11. Remaining Risks - artifact void/regeneration still has no admin UI workflow - legacy approved PDFs still need one-time migration into artifact storage - signed-URL delivery is not enabled yet; downloads are still server-streamed - storage-provider health and bucket policy checks are still operational concerns outside the app ## 12. Task J Readiness Task I leaves the app ready for: - richer artifact lifecycle tooling - legacy-file migration command - object-storage rollout beyond local development - future secure delivery strategies such as signed URLs ## 13. Verification - `npx tsc --noEmit` - `npm run gen`