Mantle2 (Drupal/PHP backend)
Mantle2 is the authoritative REST API for The Earth App. It persists users, activities, events, prompts, and articles and exposes a live OpenAPI 3.1 schema.
Core traits:
- Drupal 11.2+ with PHP 8.4+ and Symfony 7.3+ routing/controllers
- OpenAPI auto-generation from route metadata
- Security: BasicAuth (admin/ops) + Bearer JWT (end users)
- Performance: Redis caching, rate limiting, pagination helpers
- Integration: Bridges to Cloud service for AI-enriched content
Flow overview
- Client -> Mantle2 -> Controllers -> Services/DB -> Response
- Cloud -> Mantle2 (POST articles/prompts) for persistent storage
Request lifecycle
- Auth validated (Basic or Bearer)
- CORS/rate limits applied
- Controller reads inputs (query/path/body)
- Service/query + optional Redis cache
- JSON response with consistent schemas
OpenAPI docs
- Schema endpoint: /openapi (JSON)
- Swagger UI: /docs (if enabled)
ID Format Standard
All entity IDs in Mantle2 follow a 24-digit zero-padded format:
"000000000000001234567890"This format ensures:
- Consistent ID length across all entities
- Easy visual identification and debugging
- Compatibility with frontend and cloud services
- Database-agnostic ID representation
Implementation
IDs are formatted using GeneralHelper::formatId($id):
str_pad($id, 24, '0', STR_PAD_LEFT)Examples
- User ID:
"000000000000000123456789" - Activity ID:
"000000000000001234567890" - Article ID:
"000000000000002345678901" - Event ID:
"000000000000003456789012" - Prompt ID:
"000000000000004567890123" - Notification ID:
"000000000000006789012345"
Date/Time Format
All timestamps use ISO 8601 format:
"2025-01-10T16:00:00Z"Internally stored as Unix timestamps (milliseconds for events), formatted via GeneralHelper::dateToIso($timestamp).
Pagination
Standard pagination structure across all list endpoints:
{
"items": [...],
"page": 1,
"limit": 20,
"total": 42
}- Default limit: 20
- Maximum limit: 250
- Page index starts at 1
Status codes
- 200 OK, 201 Created, 204 No Content
- 400 Bad Request, 401 Unauthorized, 403 Forbidden
- 404 Not Found, 409 Conflict, 429 Too Many Requests
Common parameters
- Pagination: limit, page
- Search: search
- Sort: sort=asc|desc|rand
Common error shape
{
"error": {
"code": "E404",
"message": "Resource not found",
"details": {}
}
}Entity Types and Enums
ActivityType (29 values)
HOBBY, SPORT, WORK, STUDY, TRAVEL, SOCIAL, RELAXATION, HEALTH, PROJECT, PERSONAL_GOAL, COMMUNITY_SERVICE, CREATIVE, FAMILY, HOLIDAY, ENTERTAINMENT, LEARNING, NATURE, TECHNOLOGY, ART, SPIRITUALITY, FINANCE, HOME_IMPROVEMENT, PETS, FASHION, OTHER
EventType (3 values)
IN_PERSON— Physical event at a locationONLINE— Virtual eventHYBRID— Both in-person and online options
Visibility (3 values)
PUBLIC— Visible to all usersUNLISTED— Requires login, not in public listingsPRIVATE— Only visible to owner, admins, attendees, mutual friends
Privacy (4 values)
PUBLIC— Visible to everyoneMUTUAL— Visible to mutual friendsCIRCLE— Visible to friend circlePRIVATE— Visible only to user
Cross-service relationship
- Cloud enriches and curates content, then POSTs to Mantle2
- Crust (Nuxt) reads from Mantle2 for user-facing pages
- Ocean algorithms run in Cloud; Mantle2 remains the source of truth
Key Entities
Users
Full user profile management with authentication, privacy settings, and relationships. See users.md for complete documentation.
Example user ID: "000000000000000123456789"
Activities
Global catalog of activities users can add to their profiles. Up to 5 ActivityType tags per activity. See activities.md for complete documentation.
Example activity ID: "000000000000001234567890"
Articles
Scientific publications with user commentary and rich Ocean metadata (source, abstract, keywords, etc.). See articles.md for complete documentation.
Example article ID: "000000000000002345678901"
Events
User-organized gatherings with location, type, visibility, and attendee management. See events.md for complete documentation.
Example event ID: "000000000000003456789012"
Prompts
Daily reflection questions with user responses. PUBLIC prompts auto-expire after 2 days. See prompts.md for complete documentation.
Example prompt ID: "000000000000004567890123"
Notifications
User-scoped notifications for system events, articles, friend requests, etc. See notifications.md for complete documentation.
Example notification ID: "000000000000006789012345"
Performance & Caching
- Redis caching for frequently accessed data
- Rate limiting to prevent abuse
- Database query optimization with indexes
- Pagination to limit response sizes
- Connection pooling for database access
Security
Authentication Methods
- Basic Auth — Admin/ops access using username:password
- Bearer JWT — End-user authentication with JSON Web Tokens
Authorization
- Role-based access control (RBAC)
- Resource ownership validation
- Privacy setting enforcement
- Admin-only endpoints clearly marked
Data Protection
- Password hashing (bcrypt/argon2)
- CORS configuration
- Rate limiting
- Input validation and sanitization
- SQL injection prevention (parameterized queries)