This is a Docker-based lab environment for Okta On-Premises Provisioning (OPP) Agent with CSV directory integration. It provides a containerized setup for testing and developing Okta CSV directory integrations for user imports.
Project Name: okta-lab-csv Author: Fabio Grasso fabio.grasso@okta.com Purpose: Laboratory environment for Okta OPP Agent with CSV directory integration testing
Quick Start: See QUICKSTART.md for fast setup instructions.
The project consists of two Docker services:
- Base Image:
centos:stream9-minimal - Platform:
linux/amd64(for macOS compatibility) - Build context:
./docker/okta-opp/ - Hostname:
okta-opp-csv - Components:
- Okta Provisioning Agent
- Oracle JDK (bundled with agent)
- Volumes:
./data/okta-opp/conf→/opt/OktaProvisioningAgent/conf/- Agent configuration./data/okta-opp/logs→/opt/OktaProvisioningAgent/logs/- Agent logs./data/okta-opp/security→/opt/OktaProvisioningAgent/security/- Keystores and certificates./docker/okta-opp/packages→/packages(read-only) - RPM and certificates./csv→/csv/- CSV files for user imports
- Base Image:
python:3-alpine - Build context:
./docker/visidata/ - Components:
- VisiData terminal-based spreadsheet editor
- Python 3 runtime
- Volumes:
./csv→/data/- CSV files for interactive editing
- Purpose: Provides interactive CSV editing capabilities without installing tools on host
.
├── docker-compose.yml # Docker services definition
├── Makefile # Build and deployment commands
├── README.md # User-facing documentation
├── CLAUDE.md # This file (AI assistant documentation)
├── CHANGELOG.md # Version history and changes
├── SECURITY.md # Security policy
├── QUICKSTART.md # Quick setup guide
├── data/ # Persistent data (gitignored)
│ └── okta-opp/ # OPP Agent data
│ ├── conf/ # Agent configuration files
│ ├── logs/ # Agent logs
│ └── security/ # Keystores and certificates
├── docker/ # Docker build contexts
│ ├── okta-opp/ # OPP Agent container
│ │ ├── Dockerfile # OPP Agent image definition
│ │ ├── entrypoint.sh # OPP Agent startup script
│ │ └── packages/ # OPP Agent packages (not in git)
│ │ ├── OktaProvisioningAgent*.rpm
│ │ └── *.pem/*.crt # Optional VPN certificates
│ └── visidata/ # VisiData CSV editor container
│ └── Dockerfile # VisiData image definition
└── csv/ # CSV files directory
├── users.csv # Sample user CSV file
└── *.csv # Other CSV files for import
Before building, you must provide these files in ./docker/okta-opp/packages/:
-
OPP Agent RPM:
OktaProvisioningAgent-<version>.rpm- Required: Yes
- Download from: https://help.okta.com/oie/en-us/content/topics/provisioning/opp/opp-install-agent.htm
- Example:
OktaProvisioningAgent-03.00.06-5d254f0.x86_64.rpm
-
CA Certificates:
*.pemor*.crtfiles- Required: No (optional)
- Used for: HTTPS trust with custom VPN (e.g., Prisma Access, GlobalProtect)
- Example:
myvpn.pem - Note: Container will work without this but may not connect through custom VPN
The project includes two pre-populated CSV files in ./csv/ directory with 15 Star Wars characters:
-
Basic User CSV:
users.csv- Columns: login, email, firstName, lastName
- Users: 15 characters (Luke Skywalker, Leia Organa, Han Solo, Obi-Wan Kenobi, Yoda, Chewbacca, Padmé Amidala, Lando Calrissian, Qui-Gon Jinn, Mace Windu, Darth Vader, Darth Sidious, Wilhuff Tarkin, C-3PO, R2-D2)
- Format: CSV with header row
- Encoding: UTF-8
- Example location:
./csv/users.csv(accessible as/csv/users.csvin container)
-
Extended User CSV:
users_extended.csv- Columns: login, email, firstName, lastName, displayName, title, department, manager, employeeNumber, organization, streetAddress
- Users: Same 15 characters with extended profile attributes
- Includes: Job titles, departments, manager relationships, employee numbers, organizations (Jedi, Resistance, Empire, Droid), and addresses
- Example location:
./csv/users_extended.csv
CSV files placed in ./csv/ directory should follow these specifications:
File Format:
- Encoding: UTF-8 (mandatory)
- Delimiter: Comma (,)
- Line Endings: Unix (LF) preferred, Windows (CRLF) supported
- Header Row: First row must contain column names matching Okta user attributes
- Quoting: Use double quotes for fields containing commas or line breaks
Required Fields:
- At minimum, one unique identifier:
emailorlogin
Common User Attributes:
email- Primary email address (typically used as unique identifier)login- Username for Okta loginfirstName- User's first namelastName- User's last namemobilePhone- Mobile phone numbersecondEmail- Secondary email addressdisplayName- Display nametitle- Job titledepartment- Departmentmanager- Manager's email or login (for org chart)employeeNumber- Employee IDcostCenter- Cost center codeorganization- Organization unit
The project includes two pre-populated sample CSV files with 15 Star Wars characters:
Basic Example (./csv/users.csv):
Contains 15 users with required attributes only:
login,email,firstName,lastName
luke.skywalker@galaxy.local,luke.skywalker@galaxy.local,Luke,Skywalker
leia.organa@galaxy.local,leia.organa@galaxy.local,Leia,Organa
han.solo@galaxy.local,han.solo@galaxy.local,Han,Solo
obiwan.kenobi@galaxy.local,obiwan.kenobi@galaxy.local,Obi-Wan,Kenobi
yoda@galaxy.local,yoda@galaxy.local,Minch,Yoda
chewbacca@galaxy.local,chewbacca@galaxy.local,Chewbacca,Wookiee
padme.amidala@galaxy.local,padme.amidala@galaxy.local,Padmé,Amidala
lando.calrissian@galaxy.local,lando.calrissian@galaxy.local,Lando,Calrissian
qui-gon.jinn@galaxy.local,qui-gon.jinn@galaxy.local,Qui-Gon,Jinn
mace.windu@galaxy.local,mace.windu@galaxy.local,Mace,Windu
darth.vader@galaxy.local,darth.vader@galaxy.local,Anakin,Skywalker
darth.sidious@galaxy.local,darth.sidious@galaxy.local,Sheev,Palpatine
wilhuff.tarkin@galaxy.local,wilhuff.tarkin@galaxy.local,Wilhuff,Tarkin
c-3po@galaxy.local,c-3po@galaxy.local,C,3PO
r2-d2@galaxy.local,r2-d2@galaxy.local,R2,D2Extended Example (./csv/users_extended.csv):
Contains the same 15 users with extended profile attributes:
login,email,firstName,lastName,displayName,title,department,manager,employeeNumber,organization,streetAddress
luke.skywalker@galaxy.local,luke.skywalker@galaxy.local,Luke,Skywalker,Luke Skywalker,Jedi Knight,JEDI-COUNCIL,obiwan.kenobi@galaxy.local,10021,Jedi,"Lars Moisture Farm, Anchorhead, Tatooine"
leia.organa@galaxy.local,leia.organa@galaxy.local,Leia,Organa,Princess Leia,Princess of Alderaan,REBEL-COMMAND,,10022,Resistance,"Royal Palace, Aldera, Alderaan"
han.solo@galaxy.local,han.solo@galaxy.local,Han,Solo,Han Solo,Smuggler Captain,FREELANCE,leia.organa@galaxy.local,10023,Resistance,"Docking Bay 94, Mos Eisley, Tatooine"
...Users Included: Luke Skywalker (Jedi Knight), Leia Organa (Princess), Han Solo (Smuggler), Obi-Wan Kenobi (Jedi Master), Yoda (Grand Jedi Master), Chewbacca (Wookiee Warrior), Padmé Amidala (Queen), Lando Calrissian (Baron Administrator), Qui-Gon Jinn (Jedi Master), Mace Windu (Jedi Master), Darth Vader (Dark Lord), Darth Sidious (Emperor), Wilhuff Tarkin (Grand Moff), C-3PO (Protocol Droid), and R2-D2 (Astromech Droid).
Before importing, validate your CSV files:
- Check UTF-8 Encoding: Use
filecommand or text editor - Verify Header Row: First row must contain column names
- Check for Empty Values: Empty cells should be empty strings, not "NULL" or "null"
- Validate Email Format: Ensure email addresses are valid
- Test with Small Sample: Start with a few rows before full import
The .env file is optional for this setup. No environment variables are required for basic CSV directory integration.
If you need environment variables for custom purposes, create a .env file:
# Optional: Custom environment variables
# Add any variables needed for your specific setupThe agent waits for configuration files before starting. Required files in ./data/okta-opp/conf/:
-
OktaProvisioningAgent.conf - Must contain:
orgUrl- Your Okta org URLagentId- Agent identifierkeystoreKey- Keystore encryption keykeyPassword- Key passwordenv- Environment (preview/prod)subdomain- Okta subdomainagentKey- Agent authentication key
-
settings.conf - Java options (auto-configured by entrypoint):
JAVA_OPTS="-Xmx4096m -Dhttps.protocols=TLSv1.2"
-
Keystore:
./data/okta-opp/security/OktaProvisioningKeystore.p12
The entrypoint script creates these files if they don't exist and waits for proper configuration before starting the agent.
Configuration Method:
- Option A: Run interactive configuration:
make configure(after starting container) - Option B: Manually place configuration files in
./data/okta-opp/conf/and./data/okta-opp/security/
After the agent is running, configure CSV Directory Integration in Okta Admin Console:
-
Navigate to Directory Integrations:
- Go to Directory → Directory Integrations
- Click Add Directory
- Select CSV Directory
-
Configure Integration Settings:
- Integration Name: Descriptive name (e.g., "HR System CSV Import")
- Agent Selection: Select your registered OPP Agent
- CSV File Path: Path to CSV file inside container (e.g.,
/csv/users.csv) - Import Schedule: Configure automatic import frequency (hourly, daily, weekly)
-
Configure Attribute Mappings:
- Map CSV column names to Okta user profile attributes
- Set required fields (email, login, firstName, lastName)
- Configure optional attributes
-
Configure Matching Rules:
- Define how to match existing users (by email, login, employeeNumber)
- Choose whether to update existing users or create new ones
- Configure deactivation behavior for users missing from CSV
-
Test Import:
- Run manual import to test configuration
- Review import results and errors
- Adjust mappings as needed
The Makefile includes prerequisite checks and various deployment options:
make help # Display all available commands with descriptions
make check-prereqs # Run prerequisite checks without starting services
make build # Build Docker images (with prereq checks)
make rebuild # Force rebuild from scratch (no cache, pull latest)
make start # Check prereqs and start services in detached mode
make start-live # Check prereqs and start services in foreground (live logs)
make start-logs # Check prereqs, start detached, and follow logs
make stop # Stop and remove all containers
make restart # Stop then start services
make restart-logs # Restart and follow logs
make logs # Follow container logs (last 500 lines)
make kill # Kill containers and remove orphans
make configure # Launch interactive Okta agent configuration script
# VisiData CSV Editor Commands
docker compose exec visidata visidata /data/users.csv # Open VisiData with a specific CSV file
docker compose exec visidata sh # Access VisiData container shellThe check-prereqs target automatically runs before start, start-live, start-logs, and build commands. It verifies:
-
Okta Provisioning Agent RPM:
- Checks for:
./docker/okta-opp/packages/OktaProvisioningAgent-*.rpm - Error if missing with download link
- Checks for:
-
Certificate Files (optional):
- Checks for:
./docker/okta-opp/packages/*.pemor*.crt - Warning only (non-blocking) - container works without custom certificates but may not work with custom VPN
- Checks for:
-
CSV Directory Existence:
- Checks for:
./csv/directory - Creates directory if missing (non-blocking)
- Checks for:
The checks will exit with error code 1 if any critical prerequisite fails. Only certificates are optional (warning only).
The Makefile includes a configure target to run the interactive Okta agent configuration script:
make configureThis executes: docker compose exec okta-opp /opt/OktaProvisioningAgent/configure_agent.sh
Requirements:
- Container must be running:
make startfirst - Configuration script must exist in the container at
/opt/OktaProvisioningAgent/configure_agent.sh
Alternative: Manually configure by placing configuration files in ./data/okta-opp/conf/ (see OPP Agent Configuration section).
-
Prepare package files:
# Create package directory mkdir -p docker/okta-opp/packages # Copy OPP Agent files to docker/okta-opp/packages/: # Required: # - OktaProvisioningAgent-*.rpm # Optional (warning only): # - Certificate files (*.pem or *.crt) - for custom VPN support
-
Prepare CSV files:
# CSV directory already exists with pre-populated sample files # - users.csv (15 Star Wars characters with basic attributes) # - users_extended.csv (same users with extended attributes) # Verify CSV files ls -la csv/ cat csv/users.csv
The project includes pre-populated CSV files ready for testing. You can use these as-is or replace them with your own data.
-
Build container:
make build # Prerequisite checks will run automatically # Will fail if required RPM is missing # Will show warnings (non-blocking) if certificates are missing
-
Start service:
make start-logs # Starts the OPP Agent container and follows logs # Prerequisite checks will run automatically
-
Configure OPP Agent:
- Wait for message in okta-opp-csv logs: "⏳ Waiting for configuration files"
- Option A: Run interactive configuration:
make configure - Option B: Place configuration files manually in
./data/okta-opp/conf/ - Agent will auto-start when configuration is detected
-
Configure CSV Directory Integration in Okta:
- Navigate to Directory → Directory Integrations in Okta Admin Console
- Click Add Directory → CSV Directory
- Configure:
- Integration name
- Select the registered OPP Agent
- CSV file path:
/csv/users.csv(inside container) - Import schedule
- Attribute mappings (map CSV columns to Okta attributes)
- Matching rules (how to match existing users)
-
Run Initial Import:
- Trigger manual import from Okta Admin Console
- Monitor import progress and check for errors
- Verify users were imported correctly
-
Verify CSV File Access:
# Check CSV files are accessible from container docker compose exec okta-opp-csv ls -la /csv/ # Should show: users.csv and users_extended.csv # View CSV file contents (basic) docker compose exec okta-opp-csv cat /csv/users.csv # View CSV file contents (extended) docker compose exec okta-opp-csv cat /csv/users_extended.csv # Count users docker compose exec okta-opp-csv wc -l /csv/users.csv # Should return 16 (15 users + 1 header row)
The project uses a single container for the OPP Agent with CSV directory support:
Location: ./docker/okta-opp/entrypoint.sh
-
Display Okta ASCII logo: Visual confirmation of startup
-
Update CA certificates (if present):
- Copies
*.pemand*.crtfiles from/packages/to system trust store - Runs
update-ca-trust - Shows warning if no certificates found (non-blocking)
- Copies
-
Create required directories and set permissions:
/opt/OktaProvisioningAgent/security/opt/OktaProvisioningAgent/conf/opt/OktaProvisioningAgent/logs- Creates
settings.confandagent.logif not present
-
Configure Java options: Sets
-Xmx4096mand-Dhttps.protocols=TLSv1.2insettings.conf -
Set ownership and permissions:
- Ownership to
provisioningagent:provisioningagent - Makes JRE binaries executable
- Ownership to
-
Wait for required configuration files:
- Polls every 10 seconds
- Checks for required keys in
OktaProvisioningAgent.conf:- orgUrl, agentId, keystoreKey, keyPassword, env, subdomain, agentKey
- Verifies keystore exists at
/opt/OktaProvisioningAgent/security/OktaProvisioningKeystore.p12 - Displays "⏳ Waiting for configuration files" message until ready
-
Start OPP Agent in background:
- Executes
/opt/OktaProvisioningAgent/OktaProvisioningAgentas background process
- Executes
-
Tail agent log file: Continuously displays
/opt/OktaProvisioningAgent/logs/agent.logfor monitoring
OPP Agent Volumes:
./data/okta-opp/conf→/opt/OktaProvisioningAgent/conf/- Agent configuration./data/okta-opp/logs→/opt/OktaProvisioningAgent/logs/- Agent logs./data/okta-opp/security→/opt/OktaProvisioningAgent/security/- Keystores and certificates./docker/okta-opp/packages→/packages(read-only) - RPM and certificates./csv→/csv/- CSV files for import
CSV Files Volume:
./csv/→/csv/- CSV files are accessible at/csv/inside the container- Files can be updated on the host and are immediately available in the container
- Support for multiple CSV files with different names
All configuration, certificates, logs, and CSV files are persisted to the host filesystem and survive container restarts.
# List CSV files
ls -la ./csv/
# View CSV file contents
cat ./csv/users.csv
# Edit CSV file
nano ./csv/users.csv# List CSV files
docker compose exec okta-opp-csv ls -la /csv/
# View CSV file contents
docker compose exec okta-opp-csv cat /csv/users.csv
# Check file permissions
docker compose exec okta-opp-csv stat /csv/users.csvCSV files can be updated on the host system and changes are immediately reflected in the container due to volume mounting:
# Method 1: Edit with VisiData (interactive terminal CSV editor)
docker compose exec visidata visidata /data/users.csv
# VisiData provides spreadsheet-like editing with proper CSV format preservation
# Method 2: Edit directly on host
nano ./csv/users.csv
# Method 3: Copy new file
cp ~/Downloads/updated_users.csv ./csv/users.csv
# Method 4: Generate from script
./scripts/generate_csv.sh > ./csv/users.csvAfter updating CSV files, trigger a new import from Okta Admin Console or wait for the scheduled import.
VisiData is a terminal-based spreadsheet tool for interactive CSV editing:
Launch VisiData:
# Option 1: Direct command
docker compose exec visidata visidata /data/users.csv
# Option 2: Shell access first
docker compose exec visidata sh
# Then inside container: visidata /data/users.csvVisiData Key Bindings:
- Navigation: Arrow keys (←↑↓→) to move between cells
- Edit:
e- Edit current cell value - Add Row:
a- Add new row after current position - Delete Row:
d- Delete current row - Search:
/- Search for text in current column - Sort:
[or]- Sort column ascending/descending - Column Width:
_- Expand column width - Save:
Ctrl+S- Save changes to file - Quit:
q- Quit (prompts if unsaved changes) - Help:
z?- Show all keyboard shortcuts
Benefits:
- Maintains proper CSV formatting (quotes, escaping, UTF-8 encoding)
- Column-aware editing (stays within cell boundaries)
- Syntax highlighting for better visibility
- No need to install tools on host system
- Works with large CSV files efficiently
VisiData Container Details:
- Base Image:
python:3-alpine(lightweight) - CSV files mounted at
/data/(maps to./csv/on host) - All changes are immediately persisted to host filesystem
- Container stays running for on-demand access
docker-compose psmake logs # Container logs
docker compose logs -f okta-opp-csv # OPP Agent only (shows tailed agent.log)
# Access log files directly on host
tail -f ./data/okta-opp/logs/agent.log # OPP Agent logLog Locations:
- OPP Agent:
./data/okta-opp/logs/agent.log
- Verify configuration files exist in
./data/okta-opp/conf/ - Check for required keys in
OktaProvisioningAgent.conf:orgUrlagentIdkeystoreKeykeyPasswordenvsubdomainagentKey
- Verify keystore exists in
./data/okta-opp/security/OktaProvisioningKeystore.p12 - Check directory permissions (should be owned by
provisioningagentuser inside container) - Check logs:
docker compose logs -f okta-opp-csv - Check agent log file directly:
tail -f ./data/okta-opp/logs/agent.log
-
Verify CSV file exists:
ls -la ./csv/
-
Check file is accessible from container:
docker compose exec okta-opp-csv ls -la /csv/ docker compose exec okta-opp-csv cat /csv/users.csv
-
Verify file path in Okta configuration:
- Path must be
/csv/filename.csv(not./csv/or relative path) - Path is case-sensitive
- Path must be
-
Check file permissions:
# Ensure file is readable chmod 644 ./csv/users.csv
-
Check CSV format:
- Verify UTF-8 encoding:
file ./csv/users.csv - Check for BOM:
hexdump -C ./csv/users.csv | head -n 1 - Verify comma delimiters (not tabs or semicolons)
- Ensure header row exists
- Verify UTF-8 encoding:
-
Validate CSV content:
- Required fields present (email or login)
- No empty header columns
- Consistent number of columns per row
-
Check agent logs for errors:
grep -i csv ./data/okta-opp/logs/agent.log grep -i error ./data/okta-opp/logs/agent.log
- Verify package files exist:
- OPP Agent:
ls -la docker/okta-opp/packages/
- OPP Agent:
- Check Docker platform: Should be
linux/amd64 - Rebuild without cache:
make rebuild
If make start or make build fails with prerequisite errors:
-
Missing RPM file:
- Ensure
OktaProvisioningAgent-*.rpmis in./docker/okta-opp/packages/ - Download from Okta documentation link (see error message)
- Ensure
-
Certificate file warning (non-blocking):
- This is just a warning and won't prevent build/start
- Add
*.pemor*.crtfiles if you need custom VPN support
-
CSV directory missing:
- Directory is created automatically if missing
- Ensure
./csv/exists and contains CSV files
If make configure fails:
-
Service not running:
- Start the service first:
make start - Verify it's running:
docker compose ps okta-opp-csv
- Start the service first:
-
Configuration script doesn't exist:
- Check if script exists:
docker compose exec okta-opp-csv ls -la /opt/OktaProvisioningAgent/configure_agent.sh - Use manual configuration instead (see OPP Agent Configuration section)
- Check if script exists:
- Edit
docker/okta-opp/Dockerfileordocker/okta-opp/entrypoint.sh - Rebuild:
make rebuild - Restart:
make restart-logs
OPP Agent:
- Certificates are updated on each container start
- Source:
./docker/okta-opp/packages/*.pemor*.crt - Destination:
/etc/pki/ca-trust/source/anchors/ - Auto-update via
update-ca-trust
Adding New CSV Files:
# Simply place new CSV files in the ./csv/ directory
cp ~/path/to/new_users.csv ./csv/
# Files are immediately accessible in the container
docker compose exec okta-opp-csv ls -la /csv/CSV File Validation:
# Check file encoding
file ./csv/users.csv
# Validate CSV format
csvlint ./csv/users.csv # if csvlint is installed
# Check for BOM (Byte Order Mark) issues
hexdump -C ./csv/users.csv | head -n 1Automated CSV Generation:
Create a script to automatically generate CSV files from your data source:
#!/bin/bash
# Example: generate_csv.sh
# Your data extraction logic here
# Output to ./csv/users.csv
# Example with database export
mysql -h yourdb -u user -ppassword yourdb -e \
"SELECT email, firstName, lastName, login FROM users" \
--batch --skip-column-names | sed 's/\t/,/g' > ./csv/users.csv- Keystores and certificates are gitignored
- OPP agent runs as
provisioningagentuser (non-root) - CSV files may contain PII - ensure proper file permissions
- Protect CSV files with appropriate access controls
- Consider encrypting CSV files at rest if they contain sensitive data
- CSV directory is mounted with read-write access - ensure container security
- Container forced to
linux/amd64for macOS compatibility - May have performance implications on ARM Macs
- Ensure CSV files use UTF-8 encoding
- Windows Excel may save with BOM (Byte Order Mark) - remove if needed
- Watch for line ending issues (CRLF vs LF)
- Install the Okta Provisioning Agent
- CSV Directory Integration - Get Started
- CSV Directory Integration Prerequisites
- Okta On-Premises Provisioning Overview
- RFC 4180 - CSV Format Specification
- CentOS: Stream 9 Minimal
- Oracle JDK: 21.0.9 (bundled with OPP Agent)
- OPP Agent: Version from RPM (varies)
- Docker Compose: v2+
When configuring the CSV Directory Integration in Okta Admin Console, the file path must reference the path inside the container:
Correct Format:
/csv/users.csv
Incorrect Format (will fail):
./csv/users.csv
/Users/yourname/project/csv/users.csv
The CSV files are mounted at /csv/ inside the container via Docker volume mount.
- Encoding: UTF-8 (mandatory)
- Header Row: First row must contain column names
- Delimiter: Comma (,)
- Line Endings: Unix (LF) preferred
- Required Fields: At minimum
emailorloginfor user identification
Configure import schedule based on your needs:
- Hourly: For near-real-time imports
- Daily: For standard HR feed updates
- Weekly: For less frequent updates
- Manual: For testing or on-demand imports
This project includes multiple documentation files for different audiences:
-
QUICKSTART.md: Fast setup guide for quick deployment
- Minimal steps to get up and running
- Essential commands only
- Common issues and solutions
- Perfect for experienced users or quick testing
-
README.md: User-facing documentation with quick start, configuration guide, and troubleshooting
- Comprehensive guide with emojis, mermaid diagrams, and table of contents
- Suitable for end users and developers
- Includes badges, architecture overview, and step-by-step instructions
- Updated for CSV directory integration
-
CLAUDE.md (this file): Technical documentation for AI assistants and developers
- Detailed implementation details
- Complete directory structure
- Container architecture for CSV integration
- CSV file format specifications
- Troubleshooting guides
- Technical reference material