Developer Docs

Professional Services & Client Portals

The Professional vertical powers financial advisors, lawyers, consultants, and accountants with four integrated systems: client portals, document vaults, consultation booking, and compliance tracking. Malet Owners configure these features via the Storefront Window layout system.

NOTE

These features live in the experiences subgraph โ€” the same cross-vertical Feature Plane that houses Entertainment & Experiences. The architecture is documented in docs/architecture/18-progressive-vertical-extraction.md.


Architecture: Two-Plane Design

The Professional vertical uses the same Control + Feature plane separation as Entertainment:

  • Control Plane (malets subgraph): VerticalConfig feature flags decide which Professional modules are enabled per Malet โ€” clientPortal, documentVault, complianceTracking, consultationBooking.
  • Feature Plane (experiences subgraph): Self-contained ClientPortalModule and DocumentVaultModule. Each can be extracted to its own subgraph when a dedicated Professional vertical Team forms.
  • Extensions (services subgraph): Consultation-specific fields on existing Service and Booking entities.

Three new Storefront Window layout slot types are available: CLIENT_PORTAL, DOCUMENT_EXCHANGE, and CONSULTATION_CALENDAR.


Client Portal

Create persistent client engagements with status tracking, notes, and a shared communication timeline.

Engagement Lifecycle

ACTIVE โ†’ PAUSED โ†’ ACTIVE
       โ†’ CLOSED

Engagements start as ACTIVE when a Malet Owner onboards a new client. They can be PAUSED during inactive periods and reopened, or CLOSED permanently (with an endDate set automatically). Closed engagements cannot be reopened.

Mutations

# Create a new client engagement (Malet Owner)
mutation {
	createEngagement(
		maletId: "m_luminara"
		clientId: "v_lerato"
		title: "Tax Planning 2026"
		description: "Annual tax review and strategy session"
	) {
		id
		status
		startDate
	}
}

# Update engagement status
mutation {
	updateEngagementStatus(id: "eng_1", status: PAUSED) {
		id
		status
	}
}

# Add a note from the advisor
mutation {
	addEngagementNote(
		engagementId: "eng_1"
		content: "Reviewed Q1 financials. Recommend re-balancing investment portfolio."
		author: ADVISOR
	) {
		id
		notes {
			content
			author
			authorId
			createdAt
		}
	}
}

# Add a note from the client
mutation {
	addEngagementNote(
		engagementId: "eng_1"
		content: "Thanks for the recommendation. Proceeding with Option B."
		author: CLIENT
	) {
		id
		notes {
			content
			author
			createdAt
		}
	}
}

# Close the engagement
mutation {
	closeEngagement(id: "eng_1") {
		id
		status
		endDate
	}
}

Queries

# Visitor checks their active engagements across all Malets
query {
	myEngagements(status: ACTIVE) {
		id
		maletId
		title
		status
		startDate
		notes {
			content
			author
			createdAt
		}
	}
}

# Malet Owner views all clients
query {
	maletClients(maletId: "m_luminara") {
		id
		clientId
		title
		status
		startDate
		tags
	}
}

# Single engagement by ID
query {
	engagement(id: "eng_1") {
		id
		title
		description
		status
		notes {
			content
			author
			authorId
			createdAt
		}
	}
}

Note Authors

Each note tracks who wrote it โ€” ADVISOR (the Malet Owner or staff) or CLIENT (the Visitor). This creates a persistent communication timeline within the engagement, separate from uChat messaging.


Document Vault

Securely share contracts, invoices, reports, and compliance documents between Malet Owners and their clients. The vault stores metadata only โ€” actual files are uploaded via the existing media subgraph's R2/S3 infrastructure.

Access Levels

Level Description
OWNER_ONLY Only the Malet Owner and staff can view (default)
CLIENT_VISIBLE The associated client can also view and download
PUBLIC Visible to anyone with the link

Document Categories

Category Use Case
CONTRACT Engagement agreements, service contracts
INVOICE Bills, payment records, Murchase receipts
REPORT Financial reports, audit summaries, deliverables
IDENTITY ID verification, KYC documents
TAX Tax returns, W-9s, compliance forms
OTHER Miscellaneous documents

Retention Policies

Set retentionDays on upload to auto-compute an expiresAt date. When the retention period elapses, the document transitions to EXPIRED status via a MongoDB TTL index. Set retentionDays to 0 or omit it for indefinite retention.

Mutations

# Upload document metadata (file already uploaded via media subgraph)
mutation {
	uploadDocument(
		maletId: "m_luminara"
		fileName: "Tax_Strategy_2026.pdf"
		fileUrl: "https://r2.mallnline.com/docs/tax_strategy_2026.pdf"
		mimeType: "application/pdf"
		fileSizeBytes: 245000
		engagementId: "eng_1"
		accessLevel: CLIENT_VISIBLE
		category: REPORT
		retentionDays: 365
	) {
		id
		fileName
		accessLevel
		expiresAt
	}
}

# Archive a document (soft-archive โ€” status โ†’ ARCHIVED)
mutation {
	archiveDocument(id: "doc_1") {
		id
		status
	}
}

# Permanently delete a document (Malet Owner only)
mutation {
	deleteDocument(id: "doc_1") # Returns: true
}

Queries

# All documents for an engagement (client-facing)
query {
	engagementDocuments(engagementId: "eng_1", accessLevel: CLIENT_VISIBLE) {
		id
		fileName
		mimeType
		fileSizeBytes
		category
		createdAt
	}
}

# All documents for a Malet (Malet Owner dashboard)
query {
	maletDocuments(maletId: "m_luminara", category: CONTRACT, status: ACTIVE) {
		id
		fileName
		accessLevel
		category
		retentionDays
		expiresAt
	}
}

# Single document (logs access for compliance)
query {
	document(id: "doc_1") {
		id
		fileName
		fileUrl
		accessLevel
		accessLog {
			userId
			action
			timestamp
		}
	}
}

# Compliance audit trail
query {
	documentAccessLog(documentId: "doc_1") {
		id
		fileName
		accessLog {
			userId
			action # VIEW, DOWNLOAD, ARCHIVE
			timestamp
		}
	}
}

Compliance Access Logging

Every time a document is viewed via the document query, the requesting Visitor's ID, the action (VIEW), and a timestamp are appended to the embedded accessLog[] array. Archive operations are also logged. This creates an immutable compliance audit trail for regulated industries.


Consultation Booking

Extended booking fields for professional services on the existing services subgraph:

Service Fields

Field Type Description
consultationType ConsultationType INITIAL, FOLLOW_UP, or RETAINER
meetingUrl String Video conference link (Zoom, Teams, Google Meet)
intakeFormRequired Boolean Whether the client must complete an intake form before booking
requiresDeposit Boolean Whether a deposit is required for the consultation
depositPercentage Float Deposit as percentage of service price (e.g., 25 for 25%)

Booking Fields

Field Type Description
engagementId String Links to ClientEngagement in the experiences subgraph
meetingUrl String Copied from the Service on booking creation
intakeFormCompleted Boolean Whether the client completed the intake form
consultationNotes String Post-session notes recorded by the advisor

Example: Create a Consultation Service

mutation {
	createOneService(
		input: {
			service: {
				name: "Initial Tax Consultation"
				description: "60-minute tax planning session"
				price: 25000 # $250.00 (cents)
				maletId: "m_luminara"
				consultationType: INITIAL
				meetingUrl: "https://zoom.us/j/123456789"
				intakeFormRequired: true
				requiresDeposit: true
				depositPercentage: 25
			}
		}
	) {
		id
		name
		consultationType
		meetingUrl
	}
}

Workroom Steps

The Professional vertical ships with 4 default Workroom steps for engagement lifecycle management:

Step Type Assignee Description
Client Intake Form FORM Client Questionnaire to gather client needs before the consultation
Document Submission UPLOAD Client Upload required documents (contracts, financials, ID)
Consultation Notes FORM Malet Owner Record session notes, action items, and recommendations
Deliverables UPLOAD Malet Owner Upload final reports, signed documents, or recommendations

These steps are automatically configured on new Professional Malets via the vertical seed.


Deferred Features

The following capabilities are planned for future phases using in-house, open-source solutions โ€” no third-party SaaS dependencies:

Feature Phase Approach
E-Signatures Phase 2 Self-hosted DocSeal (MIT licensed)
Calendar Sync Phase 2 Standard CalDAV protocol (RFC 4791) + iCal .ics fallback
Retainer Billing Phase 2 Stripe Billing API + RetainerSubscription entity in murchases
Client Messaging Phase 3 Engagement-scoped channels via uChat Matrix bridge

TIP

Integration points are already designed โ€” VaultDocument.signatureStatus for e-signatures, service availability engine for CalDAV, and uChat channel auto-creation for engagement-scoped messaging.