# 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

