# Phase 1: Infrastructure Foundation - Discussion Log > **Audit trail only.** Do not use as input to planning, research, or execution agents. > Decisions are captured in CONTEXT.md — this log preserves the alternatives considered. **Date:** 2026-05-21 **Phase:** 1-Infrastructure Foundation **Areas discussed:** Schema scope, App wiring, Background worker, Env / secrets strategy --- ## Schema Scope | Option | Description | Selected | |--------|-------------|----------| | Full v1 skeleton | All tables upfront: users, refresh_tokens, quotas, documents, topics, folders, shares, audit_log, cloud_connections | ✓ | | Phase 1 minimum | Only documents + topics tables; users and auth added in Phase 2 | | | You decide | Leave scope to planner | | **User's choice:** Full v1 skeleton **Notes:** — --- | Option | Description | Selected | |--------|-------------|----------| | Yes, seed the groups table | Empty table, correct columns and FKs; avoids schema change when v2 Group admin lands | ✓ | | No, v1 tables only | Keep Phase 1 strictly to v1 requirements | | **User's choice:** Yes, seed the groups table **Notes:** PROJECT.md explicitly notes groups table will be seeded in schema. --- | Option | Description | Selected | |--------|-------------|----------| | Leave existing data on filesystem; schema empty at Phase 1 end | Phase 3 runs migration script | | | Seed a system / placeholder user | Sentinel user_id for Phase 1 uploads | | **User's choice:** (Free text) "The current documents and files are just test data and can be deleted. Please switch uploads to PostgreSQL and MinIO." **Notes:** Existing flat-file data is expendable test data. This changed the Phase 1 scope significantly: the storage service layer is rewritten in Phase 1, not Phase 3. Phase 3's data migration scope is removed. --- ## App Wiring | Option | Description | Selected | |--------|-------------|----------| | Filesystem stays active; new infra sits ready | Phase 1 only wires infra; Phase 3 switches service layer | | | Phase 1 switches uploads to PostgreSQL + MinIO | services/storage.py rewritten in Phase 1 | ✓ | **User's choice:** Phase 1 switches uploads to PostgreSQL + MinIO **Notes:** User clarified existing data is test data and can be deleted. --- | Option | Description | Selected | |--------|-------------|----------| | Seed a default/admin user in Phase 1 migration | All Phase 1 uploads attributed to placeholder user | | | Make user_id nullable for Phase 1, enforce NOT NULL in Phase 2 | Avoids phantom user; Phase 2 adds constraint | ✓ | **User's choice:** user_id nullable in Phase 1 **Notes:** — --- | Option | Description | Selected | |--------|-------------|----------| | Leave data/ directory in place | Stop writing to it; clean up manually or in Phase 3 | | | Delete data/ contents in Phase 1 | Clean break; no ambiguity about active storage | ✓ | **User's choice:** Delete data/ contents in Phase 1 **Notes:** Old data is test data only. --- | Option | Description | Selected | |--------|-------------|----------| | Single bucket 'docuvault' with user prefix paths | Standard S3 pattern; matches STORE-02 key schema | ✓ | | Per-user buckets | Stronger isolation but bucket count issues and operational complexity | | **User's choice:** Single bucket 'docuvault' **Notes:** — --- ## Background Worker | Option | Description | Selected | |--------|-------------|----------| | pgqueuer | Postgres-native; no Redis; simpler Compose | | | Celery + Redis | Battle-tested; adds Redis service | ✓ | **User's choice:** Celery + Redis **Notes:** — --- | Option | Description | Selected | |--------|-------------|----------| | Phase 1 — add it now with the other infra | All services wired together in one shot | ✓ | | Phase 3 — add when horizontal scaling needed | STORE-08 is a Phase 3 requirement | | **User's choice:** Phase 1 — add Redis + Celery now **Notes:** Redis also serves as the rate-limiting store for Phase 2 auth endpoints. --- ## Env / Secrets Strategy **User asked for best practice guidance** before answering — wanted to understand production VPS implications (root server / VPS deployment, database admin password handling). Claude explained: - App should never use PostgreSQL superuser; restricted users per principle of least privilege - Secrets stored outside project directory at `/etc/docuvault/env`; `chmod 600`, service user owned - Two DB DSNs: runtime (restricted) + migration (DDL privileges) | Option | Description | Selected | |--------|-------------|----------| | .env gitignored + .env.example committed | Docker Compose native; self-hosters copy .env.example → .env | ✓ | | Hardcoded dev defaults in docker-compose.yml | Simpler but secrets committed to git | | | docker-compose.override.yml for secrets | Flexible but extra indirection layer | | **User's choice:** .env gitignored + .env.example committed; production at `/etc/docuvault/env` --- | Env var group | Selected | |---|---| | DATABASE_URL + DATABASE_MIGRATE_URL | ✓ | | MINIO_ENDPOINT / MINIO_ROOT_USER / MINIO_ROOT_PASSWORD / MINIO_BUCKET | ✓ | | REDIS_URL | ✓ | | SECRET_KEY | ✓ | **Notes:** All four groups introduced in Phase 1. SECRET_KEY documented now for Phase 2+ use (JWT + HKDF) even though Phase 1 doesn't read it. --- | Option | Description | Selected | |--------|-------------|----------| | Yes — provision restricted users in Phase 1 | init script creates docuvault_app + docuvault_migrate | ✓ | | No — use superuser for now, split in Phase 2 | Simpler but not least-privilege | | **User's choice:** Yes — provision restricted users in Phase 1 **Notes:** — --- ## Claude's Discretion None — user made explicit choices for all areas. ## Deferred Ideas None — discussion stayed within phase scope.