481 lines
16 KiB
Markdown
481 lines
16 KiB
Markdown
# Product Requirements Document
|
|
|
|
## Product
|
|
|
|
**Name:** S3 Mover
|
|
**Document version:** 0.1
|
|
**Date:** 2026-03-26
|
|
**Status:** Draft
|
|
|
|
## Overview
|
|
|
|
S3 Mover is a web application for securely managing files across one or more S3-compatible buckets. The system provides a React frontend and Go backend, with SQLite as the system of record for users, bucket access, invitations, audit logs, and authentication-related metadata.
|
|
|
|
The existing proof of concept demonstrated that a Go backend can enumerate files and perform upload, download, and delete operations against S3-compatible object storage. This product extends that proof of concept into a production-oriented multi-user application with user management, per-user bucket credentials, invitation-based onboarding, mandatory 2FA, audit logging, and Docker deployment.
|
|
|
|
## Problem Statement
|
|
|
|
The proof of concept is functionally viable, but it is not suitable for real users because:
|
|
|
|
- There is no user management or role-based access control.
|
|
- Storage credentials are configured globally instead of per user and per bucket.
|
|
- There is no secure onboarding flow.
|
|
- There is no multi-factor authentication.
|
|
- There is no audit trail for file operations.
|
|
- Sensitive bucket configuration is not yet modeled as protected server-side data.
|
|
|
|
The product must evolve into a secure internal application that allows administrators to manage users and user-specific bucket credentials, while allowing standard users to operate only on the buckets assigned to them.
|
|
|
|
## Goals
|
|
|
|
- Provide secure user authentication using email, password, and TOTP-based 2FA.
|
|
- Support administrator-led invitation onboarding via Resend email.
|
|
- Allow administrators to manage users and assign one or more bucket configurations to each user.
|
|
- Keep all sensitive bucket credentials server-side only.
|
|
- Provide file browsing and upload, download, and delete capabilities for the assigned bucket(s) of a logged-in user.
|
|
- Record auditable logs of bucket operations.
|
|
- Persist system data in SQLite.
|
|
- Package the application for Docker deployment.
|
|
|
|
## Non-Goals
|
|
|
|
- End-user self-registration.
|
|
- SSO, SAML, or OAuth identity providers in the first release.
|
|
- Bucket creation or infrastructure provisioning.
|
|
- Advanced IAM policy editing or credential rotation workflows.
|
|
- Object versioning, lifecycle management, or ACL management.
|
|
- Bulk file operations beyond single upload, download, and delete.
|
|
- Fine-grained per-prefix authorization within a bucket in the first release.
|
|
|
|
## Users and Roles
|
|
|
|
### Administrator
|
|
|
|
The administrator manages the system and has access to all administrative functions.
|
|
|
|
Capabilities:
|
|
|
|
- Log in with email, password, and TOTP
|
|
- View all registered users
|
|
- View details for an individual user
|
|
- Invite a new user by email
|
|
- Delete a user account
|
|
- Add one or more bucket credential sets to a user
|
|
- Remove a bucket credential set from a user
|
|
- View audit logs for all file operations
|
|
|
|
### Standard User
|
|
|
|
The standard user interacts only with buckets assigned to their account.
|
|
|
|
Capabilities:
|
|
|
|
- Complete invitation onboarding
|
|
- Set a strong password
|
|
- Enroll a TOTP authenticator during first-time setup
|
|
- Log in with email, password, and TOTP
|
|
- View the list of assigned buckets in a left sidebar
|
|
- Select a bucket and view its contents
|
|
- Upload, download, and delete files within assigned buckets
|
|
|
|
## Key User Journeys
|
|
|
|
### 1. Administrator Invites a User
|
|
|
|
1. Administrator logs into the application.
|
|
2. Administrator navigates to the user management page.
|
|
3. Administrator creates a new user by entering at least an email address.
|
|
4. System creates a pending user record and a time-limited invitation token.
|
|
5. System sends an invitation email through Resend.
|
|
6. Email contains a secure link to the onboarding page.
|
|
|
|
### 2. User Accepts Invite and Creates Credentials
|
|
|
|
1. User clicks the invitation link.
|
|
2. System validates the invitation token.
|
|
3. User is prompted to set a strong password.
|
|
4. User is required to enroll a TOTP authenticator before activation completes.
|
|
5. User confirms setup by entering a valid TOTP code.
|
|
6. System activates the account and marks the invitation as consumed.
|
|
|
|
### 3. User Logs In
|
|
|
|
1. User enters email address and password.
|
|
2. System validates credentials.
|
|
3. User is prompted for a TOTP code.
|
|
4. System issues a JWT after successful second-factor verification.
|
|
5. User is redirected to the main application.
|
|
|
|
### 4. User Operates on a Bucket
|
|
|
|
1. User logs in successfully.
|
|
2. User sees a sidebar listing assigned buckets.
|
|
3. User selects a bucket.
|
|
4. System displays the bucket name and endpoint at the top of the page.
|
|
5. System shows a paginated file list with 15 items per page.
|
|
6. User uploads, downloads, or deletes files.
|
|
7. System records an audit log entry for each file operation.
|
|
|
|
### 5. Administrator Manages Bucket Credentials for a User
|
|
|
|
1. Administrator navigates to a user detail page.
|
|
2. Administrator adds a bucket credential set for that user.
|
|
3. Administrator enters:
|
|
- AWS access key ID
|
|
- AWS secret access key
|
|
- AWS region
|
|
- bucket name
|
|
- S3-compatible endpoint
|
|
4. System stores those credentials securely in SQLite.
|
|
5. User gains access to that bucket after next authorized fetch or session refresh.
|
|
6. Administrator may remove a bucket configuration from the user later.
|
|
|
|
## Functional Requirements
|
|
|
|
## FR-1 Authentication
|
|
|
|
- The system shall support login using email address and password.
|
|
- The system shall require TOTP as a second factor for all users.
|
|
- The system shall issue JWTs for authenticated API access.
|
|
- The system shall reject access to protected routes without a valid JWT.
|
|
- The system shall support logout by invalidating the client session.
|
|
|
|
## FR-2 Invitation and Onboarding
|
|
|
|
- Only an administrator may create a new user.
|
|
- Creating a user shall generate an invite email sent through Resend.
|
|
- The invite shall contain a secure, time-limited, single-use token.
|
|
- The invite flow shall require the user to set a strong password.
|
|
- The invite flow shall require TOTP setup before account activation.
|
|
- An invited user shall not be able to log in until onboarding is complete.
|
|
|
|
## FR-3 User Management
|
|
|
|
- The administrator shall have a page listing all users.
|
|
- The user list shall include at minimum email address, status, role, created date, and last login date if available.
|
|
- The administrator shall be able to click into a user detail page.
|
|
- The administrator shall be able to delete a user account.
|
|
- Deleting a user shall revoke future access immediately.
|
|
|
|
## FR-4 Bucket Assignment
|
|
|
|
- A user shall be assigned at least one bucket credential set to access storage.
|
|
- A user may have multiple bucket credential sets.
|
|
- Each bucket credential set shall be unique to the user and shall not be shared by design.
|
|
- The administrator shall be able to create, view metadata for, and remove bucket assignments for a user.
|
|
- Sensitive values such as access keys and secrets shall not be shown back to the browser after creation, except where explicitly required for a masked administrative UX.
|
|
|
|
## FR-5 Bucket Browsing and File Operations
|
|
|
|
- A logged-in user shall see assigned buckets in a left sidebar.
|
|
- Selecting a bucket shall show:
|
|
- bucket name
|
|
- endpoint
|
|
- paginated file listing
|
|
- Pagination shall be fixed at 15 items per page.
|
|
- The system shall support upload, download, and delete operations for files in the selected bucket.
|
|
- The system shall support S3-compatible providers, not just AWS S3.
|
|
|
|
## FR-6 Audit Logging
|
|
|
|
- The system shall log all user file operations.
|
|
- Each log entry shall include at minimum:
|
|
- timestamp
|
|
- user ID
|
|
- user email
|
|
- bucket identifier
|
|
- file key
|
|
- operation type
|
|
- The operation type shall support at minimum:
|
|
- upload
|
|
- download
|
|
- delete
|
|
- Only administrators shall be able to view logs.
|
|
|
|
## FR-7 Administrative Access Control
|
|
|
|
- Only administrators shall be able to:
|
|
- invite users
|
|
- view all users
|
|
- view user details
|
|
- manage user bucket assignments
|
|
- delete users
|
|
- view audit logs
|
|
|
|
## FR-8 Deployment and Runtime
|
|
|
|
- The application shall run in Docker.
|
|
- The backend shall be implemented in Go.
|
|
- The frontend shall be implemented in React.
|
|
- SQLite shall be the primary application database.
|
|
|
|
## Security Requirements
|
|
|
|
- Sensitive bucket credentials shall never be sent to the browser.
|
|
- Sensitive bucket credentials shall never be included in JWT payloads.
|
|
- JWTs shall be signed server-side with a configurable secret or private key.
|
|
- Passwords shall be stored only as strong salted hashes.
|
|
- TOTP secrets shall be stored securely server-side.
|
|
- Invite tokens shall be stored hashed or otherwise protected server-side and shall expire.
|
|
- The application shall enforce HTTPS in deployed environments.
|
|
- The application shall implement CSRF protections if JWTs are stored in cookies.
|
|
- The application shall implement rate limiting or equivalent brute-force protection for authentication endpoints.
|
|
- All sensitive configuration shall be provided through environment variables or secret injection at runtime.
|
|
- Administrative and user actions shall be authorized server-side for every request.
|
|
|
|
## UX Requirements
|
|
|
|
### Authentication
|
|
|
|
- The application shall provide:
|
|
- login page
|
|
- TOTP challenge page
|
|
- invitation acceptance page
|
|
- password setup form
|
|
- TOTP enrollment page with QR code and manual key fallback
|
|
|
|
### Main User Application
|
|
|
|
- The main authenticated layout shall include:
|
|
- left sidebar for bucket selection
|
|
- top area showing selected bucket name and endpoint
|
|
- file listing view
|
|
- pagination controls
|
|
- upload action
|
|
- download action
|
|
- delete action
|
|
|
|
### Administration
|
|
|
|
- The administrator area shall include:
|
|
- user list page
|
|
- user detail page
|
|
- add bucket assignment flow
|
|
- audit log page
|
|
|
|
## Data Model Requirements
|
|
|
|
The following logical entities are required.
|
|
|
|
### users
|
|
|
|
- id
|
|
- email
|
|
- role
|
|
- status
|
|
- password_hash
|
|
- totp_secret
|
|
- totp_enabled
|
|
- invited_at
|
|
- activated_at
|
|
- last_login_at
|
|
- created_at
|
|
- updated_at
|
|
|
|
### invitations
|
|
|
|
- id
|
|
- user_id
|
|
- email
|
|
- token_hash
|
|
- expires_at
|
|
- consumed_at
|
|
- created_by_user_id
|
|
- created_at
|
|
|
|
### user_bucket_credentials
|
|
|
|
- id
|
|
- user_id
|
|
- display_name
|
|
- aws_access_key_id
|
|
- aws_secret_access_key
|
|
- aws_region
|
|
- s3_bucket
|
|
- aws_endpoint_url
|
|
- use_path_style
|
|
- created_at
|
|
- updated_at
|
|
|
|
### audit_logs
|
|
|
|
- id
|
|
- user_id
|
|
- user_email
|
|
- bucket_credential_id
|
|
- bucket_name
|
|
- endpoint
|
|
- file_key
|
|
- operation
|
|
- created_at
|
|
- request_ip
|
|
- user_agent
|
|
|
|
### sessions or token metadata
|
|
|
|
Implementation may use stateless JWTs only, but the design should allow optional storage for token revocation, refresh sessions, or login tracking if needed.
|
|
|
|
## Recommended Status Values
|
|
|
|
### User status
|
|
|
|
- invited
|
|
- active
|
|
- disabled
|
|
|
|
### Role
|
|
|
|
- admin
|
|
- user
|
|
|
|
### Audit operation
|
|
|
|
- upload
|
|
- download
|
|
- delete
|
|
|
|
## API Requirements
|
|
|
|
The final API shape may change, but the following resources are expected.
|
|
|
|
### Authentication
|
|
|
|
- `POST /api/auth/login`
|
|
- `POST /api/auth/totp/verify`
|
|
- `POST /api/auth/logout`
|
|
- `GET /api/auth/me`
|
|
|
|
### Invitations
|
|
|
|
- `POST /api/admin/users/invite`
|
|
- `GET /api/invitations/:token`
|
|
- `POST /api/invitations/:token/accept`
|
|
|
|
### Administration
|
|
|
|
- `GET /api/admin/users`
|
|
- `GET /api/admin/users/:userId`
|
|
- `DELETE /api/admin/users/:userId`
|
|
- `POST /api/admin/users/:userId/buckets`
|
|
- `DELETE /api/admin/users/:userId/buckets/:bucketCredentialId`
|
|
- `GET /api/admin/audit-logs`
|
|
|
|
### User bucket access
|
|
|
|
- `GET /api/me/buckets`
|
|
- `GET /api/me/buckets/:bucketCredentialId/files?page=1&pageSize=15`
|
|
- `POST /api/me/buckets/:bucketCredentialId/files`
|
|
- `GET /api/me/buckets/:bucketCredentialId/files/:key`
|
|
- `DELETE /api/me/buckets/:bucketCredentialId/files/:key`
|
|
|
|
## Business Rules
|
|
|
|
- Every non-admin user must authenticate with password plus TOTP.
|
|
- An invitation may only be used once.
|
|
- A bucket credential set belongs to exactly one user.
|
|
- A user may have zero bucket assignments during setup or after administrative changes, but a user must have at least one assignment to perform storage operations.
|
|
- The server shall resolve storage access from the selected bucket credential ID and not from any client-supplied raw credential values.
|
|
- The browser may know a bucket display name, bucket name, and endpoint, but not secret credentials.
|
|
|
|
## Technical Requirements
|
|
|
|
### Backend
|
|
|
|
- Go HTTP API
|
|
- SQLite persistence
|
|
- JWT authentication middleware
|
|
- Password hashing using a modern algorithm such as Argon2id or bcrypt
|
|
- TOTP support using a standard authenticator-compatible implementation
|
|
- Resend integration for invitation emails
|
|
- S3-compatible client abstraction for storage operations
|
|
- Audit log persistence for all storage mutations and downloads
|
|
|
|
### Frontend
|
|
|
|
- React application
|
|
- Authenticated routing
|
|
- Admin-only views and user views
|
|
- Sidebar bucket navigation
|
|
- Paginated bucket file list with page size fixed to 15
|
|
- Forms for onboarding, login, TOTP verification, user management, and bucket assignment
|
|
|
|
### Infrastructure and Deployment
|
|
|
|
- Single Docker image or Docker Compose-based local runtime
|
|
- Persistent storage volume for SQLite database
|
|
- Environment-based configuration for JWT secret, Resend API key, and bootstrap admin settings
|
|
|
|
## Reporting and Logging Requirements
|
|
|
|
- Application logs shall capture authentication failures, invitation events, administrative changes, and storage operation failures.
|
|
- Audit logs shall be queryable by administrators.
|
|
- Audit log views should support filtering by:
|
|
- date range
|
|
- user
|
|
- bucket
|
|
- operation
|
|
|
|
## Constraints
|
|
|
|
- SQLite is the required datastore for the initial production-ready version.
|
|
- The frontend must not directly communicate with S3-compatible storage using raw bucket credentials.
|
|
- All storage operations must be proxied through the Go backend.
|
|
- Sensitive settings must remain server-side.
|
|
|
|
## Assumptions
|
|
|
|
- The first release supports one administrator bootstrap path via environment configuration, migration seed, or initial setup command.
|
|
- Invitation emails will be transactional emails sent through Resend.
|
|
- TOTP apps such as 1Password, Google Authenticator, or Authy are acceptable authenticators.
|
|
- The application is intended for trusted organizational users rather than open public sign-up.
|
|
|
|
## Open Questions
|
|
|
|
- How should the first administrator account be bootstrapped?
|
|
- Should administrators also be able to perform bucket operations, or only manage users and logs?
|
|
- Should deleted users be hard-deleted or soft-deleted for audit retention?
|
|
- Should bucket secrets be encrypted at rest in SQLite using an application-level encryption key?
|
|
- Should JWTs be short-lived access tokens only, or should the system also support refresh tokens?
|
|
- What are the password strength rules beyond “strong password”?
|
|
- What is the invite expiration window?
|
|
- Should audit logs include failed file operations in addition to successful ones?
|
|
- Is account disablement required in addition to deletion?
|
|
- Are per-user bucket display names needed in the UI, or is raw bucket name sufficient?
|
|
|
|
## Success Criteria
|
|
|
|
- Administrators can invite, onboard, and manage users without manual database changes.
|
|
- Standard users can access only their assigned buckets.
|
|
- Bucket credentials never appear in browser network payloads or rendered UI.
|
|
- Users must complete TOTP enrollment before account activation.
|
|
- All file uploads, downloads, and deletes are auditable by administrators.
|
|
- The application runs successfully in Docker with SQLite persistence.
|
|
|
|
## Proposed Delivery Phases
|
|
|
|
### Phase 1: Identity and Administration Foundation
|
|
|
|
- SQLite schema and migrations
|
|
- bootstrap administrator
|
|
- login, password hashing, JWT issuance
|
|
- TOTP enrollment and verification
|
|
- invite flow with Resend
|
|
- admin user list and user detail pages
|
|
|
|
### Phase 2: Bucket Assignment and Secure Access
|
|
|
|
- per-user bucket credential storage
|
|
- admin create and remove bucket credentials
|
|
- authenticated bucket list API
|
|
- user sidebar and selected-bucket view
|
|
- secure server-side storage operations using assigned credentials
|
|
|
|
### Phase 3: Auditability and Production Hardening
|
|
|
|
- audit log persistence and admin log viewer
|
|
- Docker packaging
|
|
- operational logging and error handling
|
|
- rate limiting and security hardening
|
|
- UX polish and edge-case handling
|
|
|