Replacing Oracle UCM with Azure-Native Document Management
Legacy document management systems like Oracle UCM are expensive, inflexible, and painful to maintain. I built AssuranceNet — an Azure-native replacement that demonstrates how to modernize document management with cloud-native services and modern development practices.
The Legacy Problem
Oracle UCM (now WebCenter Content) was built for a different era. Organizations running it face:
- High licensing costs — Oracle licensing alone can exceed cloud-native alternatives by 10x
- Complex infrastructure — WebLogic servers, Oracle databases, custom integrations
- Poor developer experience — SOAP APIs, proprietary SDKs, minimal documentation
- No cloud path — Lift-and-shift doesn't work for monolithic content platforms
The Azure-Native Solution
AssuranceNet replaces UCM's core capabilities with Azure services purpose-built for document management:
| Capability | Oracle UCM | AssuranceNet (Azure) |
|---|---|---|
| Document Storage | Oracle Database + filesystem | Azure Blob Storage (versioned) |
| Metadata & Search | UCM metadata framework | Azure SQL + full-text search |
| Authentication | Oracle SSO / LDAP | Entra ID + MSAL |
| API | SOAP / RIDC | FastAPI REST + OpenAPI |
| PDF Processing | Custom converters | Pluggable engine (Aspose/Gotenberg) |
| Malware Scanning | Third-party add-on | Built-in two-phase upload with staging |
| Infrastructure | WebLogic + Oracle DB | Container Apps + Managed Identity |
Key Features
Explicit Document Versioning
Unlike many DMS platforms that show version history by default, AssuranceNet enforces latest-only visibility for end users. Only administrators can access previous versions — preventing confusion and reducing storage browsing complexity:
# Simplified version model
class DocumentVersion(Base):
document_id: UUID # Parent document
version_number: int # Auto-incremented
is_latest: bool # Only one per document
blob_path: str # Azure Blob URL
original_filename: str
content_type: str
file_size: int
uploaded_by: str
# On new version upload:
# 1. Previous latest → is_latest = False
# 2. New version → is_latest = True
# 3. End users only see latest
Two-Phase Upload with Malware Scanning
Documents never go directly to production storage. Every upload flows through a staging container where malware scanning occurs before promotion:
Upload Flow:
1. File → Staging Blob Container
2. Malware scan (configurable engine)
3. If clean → Move to production container
4. If infected → Quarantine + alert
5. Metadata written to Azure SQL
Type-Based PDF Merge
Investigation documents can be merged into a single PDF with ordering determined by document type priority. This is critical for regulatory workflows where document order matters for compliance submissions.
Infrastructure as Code
The entire infrastructure is defined in Azure Bicep:
// Core infrastructure modules
module storage 'modules/storage.bicep' = {
params: {
location: location
storageAccountName: storageAccountName
// Versioned containers for documents
containers: ['assurancenet-documents', 'assurancenet-staging']
}
}
module sql 'modules/sql.bicep' = {
params: {
location: location
// Managed Identity auth — no connection strings
administratorLogin: 'sqladmin'
}
}
module containerApp 'modules/container-app.bicep' = {
params: {
// Managed Identity binds everything together
managedIdentityId: identity.outputs.principalId
}
}
Architecture Decision Records
The repo includes 6 formal ADRs documenting key architectural choices — version visibility model, PDF engine selection, auth strategy, blob storage design, API versioning approach, and RBAC implementation. This is how production systems should document their "why."
Getting Started
# Clone and initialize
git clone https://github.com/fgarofalo56/ucm-azure-native-demo.git
cd ucm-azure-native-demo
# Local development setup
./scripts/setup/init-dev.sh
# Deploy to Azure
az deployment group create \
--resource-group rg-assurancenet \
--template-file infra/main.bicep
Full source, documentation, and deployment guides: fgarofalo56/ucm-azure-native-demo